From 48661227ead921980022e9c0afe570cae167bc09 Mon Sep 17 00:00:00 2001 From: jpbl <jpbl> Date: Tue, 20 Dec 2005 14:57:51 +0000 Subject: [PATCH] added missing qt files --- src/gui/qt/Account.cpp | 60 + src/gui/qt/Account.hpp | 67 + src/gui/qt/Call.cpp | 141 +++ src/gui/qt/Call.hpp | 142 +++ src/gui/qt/CallManager.hpp | 30 + src/gui/qt/CallManagerImpl.cpp | 68 + src/gui/qt/CallManagerImpl.hpp | 53 + src/gui/qt/CallStatus.cpp | 56 + src/gui/qt/CallStatus.hpp | 41 + src/gui/qt/CallStatusFactory.hpp | 29 + src/gui/qt/ConfigurationManager.hpp | 30 + src/gui/qt/ConfigurationManagerImpl.cpp | 168 +++ src/gui/qt/ConfigurationManagerImpl.hpp | 174 +++ src/gui/qt/ConfigurationPanel.ui | 1497 +++++++++++++++++++++++ src/gui/qt/ConfigurationPanel.ui.h | 389 ++++++ src/gui/qt/ConfigurationPanelImpl.cpp | 71 ++ src/gui/qt/ConfigurationPanelImpl.hpp | 69 ++ src/gui/qt/DebugOutput.hpp | 30 + src/gui/qt/DebugOutputImpl.cpp | 32 + src/gui/qt/DebugOutputImpl.hpp | 37 + src/gui/qt/Event.cpp | 73 ++ src/gui/qt/Event.hpp | 63 + src/gui/qt/EventFactory.hpp | 98 ++ src/gui/qt/EventFactory.inl | 95 ++ src/gui/qt/Factory.hpp | 58 + src/gui/qt/Factory.inl | 52 + src/gui/qt/JPushButton.cpp | 153 +++ src/gui/qt/JPushButton.hpp | 80 ++ src/gui/qt/Launcher.cpp | 93 ++ src/gui/qt/Launcher.hpp | 52 + src/gui/qt/Makefile.am | 5 +- src/gui/qt/NumericKeypad.cpp | 265 ++++ src/gui/qt/NumericKeypad.hpp | 80 ++ src/gui/qt/ObjectFactory.hpp | 98 ++ src/gui/qt/ObjectFactory.inl | 95 ++ src/gui/qt/ObjectPool.hpp | 53 + src/gui/qt/ObjectPool.inl | 51 + src/gui/qt/PhoneLine.cpp | 435 +++++++ src/gui/qt/PhoneLine.hpp | 184 +++ src/gui/qt/PhoneLineButton.cpp | 81 ++ src/gui/qt/PhoneLineButton.hpp | 65 + src/gui/qt/PhoneLineLocker.cpp | 39 + src/gui/qt/PhoneLineLocker.hpp | 51 + src/gui/qt/PhoneLineManager.hpp | 30 + src/gui/qt/PhoneLineManagerImpl.cpp | 750 ++++++++++++ src/gui/qt/PhoneLineManagerImpl.hpp | 350 ++++++ src/gui/qt/QjListBoxPixmap.cpp | 159 +++ src/gui/qt/QjListBoxPixmap.hpp | 73 ++ src/gui/qt/Request.cpp | 243 ++++ src/gui/qt/Request.hpp | 245 ++++ src/gui/qt/Requester.hpp | 30 + src/gui/qt/RequesterImpl.cpp | 200 +++ src/gui/qt/RequesterImpl.hpp | 150 +++ src/gui/qt/RequesterImpl.inl | 40 + src/gui/qt/SFLCallStatus.hpp | 35 + src/gui/qt/SFLEvents.cpp | 144 +++ src/gui/qt/SFLEvents.hpp | 102 ++ src/gui/qt/SFLLcd.cpp | 316 +++++ src/gui/qt/SFLLcd.hpp | 88 ++ src/gui/qt/SFLPhoneApp.cpp | 266 ++++ src/gui/qt/SFLPhoneApp.hpp | 68 + src/gui/qt/SFLPhoneWindow.cpp | 261 ++++ src/gui/qt/SFLPhoneWindow.hpp | 132 ++ src/gui/qt/SFLRequest.cpp | 417 +++++++ src/gui/qt/SFLRequest.hpp | 279 +++++ src/gui/qt/Session.cpp | 181 +++ src/gui/qt/Session.hpp | 122 ++ src/gui/qt/SessionFactory.hpp | 56 + src/gui/qt/SessionIO.hpp | 61 + src/gui/qt/SessionIOFactory.hpp | 31 + src/gui/qt/SkinManager.hpp | 30 + src/gui/qt/SkinManagerImpl.cpp | 78 ++ src/gui/qt/SkinManagerImpl.hpp | 69 ++ src/gui/qt/TCPSessionIO.cpp | 140 +++ src/gui/qt/TCPSessionIO.hpp | 101 ++ src/gui/qt/TCPSessionIOCreator.cpp | 39 + src/gui/qt/TCPSessionIOCreator.hpp | 41 + src/gui/qt/TransparentWidget.cpp | 125 ++ src/gui/qt/TransparentWidget.hpp | 66 + src/gui/qt/Url.cpp | 62 + src/gui/qt/Url.hpp | 33 + src/gui/qt/VolumeControl.cpp | 173 +++ src/gui/qt/VolumeControl.hpp | 75 ++ src/gui/qt/globals.h | 55 + src/gui/qt/main.cpp | 83 ++ 85 files changed, 11500 insertions(+), 2 deletions(-) create mode 100644 src/gui/qt/Account.cpp create mode 100644 src/gui/qt/Account.hpp create mode 100644 src/gui/qt/Call.cpp create mode 100644 src/gui/qt/Call.hpp create mode 100644 src/gui/qt/CallManager.hpp create mode 100644 src/gui/qt/CallManagerImpl.cpp create mode 100644 src/gui/qt/CallManagerImpl.hpp create mode 100644 src/gui/qt/CallStatus.cpp create mode 100644 src/gui/qt/CallStatus.hpp create mode 100644 src/gui/qt/CallStatusFactory.hpp create mode 100644 src/gui/qt/ConfigurationManager.hpp create mode 100644 src/gui/qt/ConfigurationManagerImpl.cpp create mode 100644 src/gui/qt/ConfigurationManagerImpl.hpp create mode 100644 src/gui/qt/ConfigurationPanel.ui create mode 100644 src/gui/qt/ConfigurationPanel.ui.h create mode 100644 src/gui/qt/ConfigurationPanelImpl.cpp create mode 100644 src/gui/qt/ConfigurationPanelImpl.hpp create mode 100644 src/gui/qt/DebugOutput.hpp create mode 100644 src/gui/qt/DebugOutputImpl.cpp create mode 100644 src/gui/qt/DebugOutputImpl.hpp create mode 100644 src/gui/qt/Event.cpp create mode 100644 src/gui/qt/Event.hpp create mode 100644 src/gui/qt/EventFactory.hpp create mode 100644 src/gui/qt/EventFactory.inl create mode 100644 src/gui/qt/Factory.hpp create mode 100644 src/gui/qt/Factory.inl create mode 100644 src/gui/qt/JPushButton.cpp create mode 100644 src/gui/qt/JPushButton.hpp create mode 100644 src/gui/qt/Launcher.cpp create mode 100644 src/gui/qt/Launcher.hpp create mode 100644 src/gui/qt/NumericKeypad.cpp create mode 100644 src/gui/qt/NumericKeypad.hpp create mode 100644 src/gui/qt/ObjectFactory.hpp create mode 100644 src/gui/qt/ObjectFactory.inl create mode 100644 src/gui/qt/ObjectPool.hpp create mode 100644 src/gui/qt/ObjectPool.inl create mode 100644 src/gui/qt/PhoneLine.cpp create mode 100644 src/gui/qt/PhoneLine.hpp create mode 100644 src/gui/qt/PhoneLineButton.cpp create mode 100644 src/gui/qt/PhoneLineButton.hpp create mode 100644 src/gui/qt/PhoneLineLocker.cpp create mode 100644 src/gui/qt/PhoneLineLocker.hpp create mode 100644 src/gui/qt/PhoneLineManager.hpp create mode 100644 src/gui/qt/PhoneLineManagerImpl.cpp create mode 100644 src/gui/qt/PhoneLineManagerImpl.hpp create mode 100644 src/gui/qt/QjListBoxPixmap.cpp create mode 100644 src/gui/qt/QjListBoxPixmap.hpp create mode 100644 src/gui/qt/Request.cpp create mode 100644 src/gui/qt/Request.hpp create mode 100644 src/gui/qt/Requester.hpp create mode 100644 src/gui/qt/RequesterImpl.cpp create mode 100644 src/gui/qt/RequesterImpl.hpp create mode 100644 src/gui/qt/RequesterImpl.inl create mode 100644 src/gui/qt/SFLCallStatus.hpp create mode 100644 src/gui/qt/SFLEvents.cpp create mode 100644 src/gui/qt/SFLEvents.hpp create mode 100644 src/gui/qt/SFLLcd.cpp create mode 100644 src/gui/qt/SFLLcd.hpp create mode 100644 src/gui/qt/SFLPhoneApp.cpp create mode 100644 src/gui/qt/SFLPhoneApp.hpp create mode 100644 src/gui/qt/SFLPhoneWindow.cpp create mode 100644 src/gui/qt/SFLPhoneWindow.hpp create mode 100644 src/gui/qt/SFLRequest.cpp create mode 100644 src/gui/qt/SFLRequest.hpp create mode 100644 src/gui/qt/Session.cpp create mode 100644 src/gui/qt/Session.hpp create mode 100644 src/gui/qt/SessionFactory.hpp create mode 100644 src/gui/qt/SessionIO.hpp create mode 100644 src/gui/qt/SessionIOFactory.hpp create mode 100644 src/gui/qt/SkinManager.hpp create mode 100644 src/gui/qt/SkinManagerImpl.cpp create mode 100644 src/gui/qt/SkinManagerImpl.hpp create mode 100644 src/gui/qt/TCPSessionIO.cpp create mode 100644 src/gui/qt/TCPSessionIO.hpp create mode 100644 src/gui/qt/TCPSessionIOCreator.cpp create mode 100644 src/gui/qt/TCPSessionIOCreator.hpp create mode 100644 src/gui/qt/TransparentWidget.cpp create mode 100644 src/gui/qt/TransparentWidget.hpp create mode 100644 src/gui/qt/Url.cpp create mode 100644 src/gui/qt/Url.hpp create mode 100644 src/gui/qt/VolumeControl.cpp create mode 100644 src/gui/qt/VolumeControl.hpp create mode 100644 src/gui/qt/globals.h create mode 100644 src/gui/qt/main.cpp diff --git a/src/gui/qt/Account.cpp b/src/gui/qt/Account.cpp new file mode 100644 index 0000000000..79b7c55382 --- /dev/null +++ b/src/gui/qt/Account.cpp @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Account.hpp" +#include "Requester.hpp" +#include "Call.hpp" + +Account::Account(const QString &sessionId, + const QString &name) + : mSessionId(sessionId) + , mId(name) +{} + +Request * +Account::registerAccount() const +{ + std::list< QString > args; + args.push_back(mId); + return Requester::instance().send(mSessionId, "register", args); +} + +Request * +Account::unregisterAccount() const +{ + std::list< QString > args; + args.push_back(mId); + return Requester::instance().send(mSessionId, "unregister", args); +} + +Request * +Account::createCall(Call * &call, const QString &to) const +{ + QString callId = Requester::instance().generateCallId(); + call = new Call(mSessionId, mId, callId, to); + + std::list< QString> args; + args.push_back(mId); + args.push_back(callId); + args.push_back(to); + return Requester::instance().send(mSessionId, "call", args); +} + + diff --git a/src/gui/qt/Account.hpp b/src/gui/qt/Account.hpp new file mode 100644 index 0000000000..d298b8c162 --- /dev/null +++ b/src/gui/qt/Account.hpp @@ -0,0 +1,67 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef SFLPHONEGUI_ACCOUNT_H +#define SFLPHONEGUI_ACCOUNT_H + +#include <qstring.h> + +#include "Call.hpp" + +class Request; + +class Account { + public: + Account(const QString &sessionId, + const QString &name); + + /** + * This will generate a call ready to be used. + */ + Request *registerAccount() const; + Request *unregisterAccount() const; + + /** + * This function will create a call. The call pointer will + * point to a newly allocated memory. You're responsible for + * deleting this memory. + */ + Request *createCall(Call * &call, const QString &to) const; + + + QString id() const + {return mId;} + +private: + Account(); + + /** + * This is the session id that we are related to. + */ + QString mSessionId; + + /** + * This is the account id that we are related to. + */ + QString mId; +}; + + +#endif diff --git a/src/gui/qt/Call.cpp b/src/gui/qt/Call.cpp new file mode 100644 index 0000000000..e538641c9c --- /dev/null +++ b/src/gui/qt/Call.cpp @@ -0,0 +1,141 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qstring.h> +#include <list> + +#include "Account.hpp" +#include "Call.hpp" +#include "CallManager.hpp" +#include "Session.hpp" +#include "Requester.hpp" + + +Call::Call(const QString &sessionId, + const QString &accountId, + const QString &callId, + const QString &peer, + bool incomming) + : mSessionId(sessionId) + , mAccountId(accountId) + , mId(callId) + , mPeer(peer) + , mIsIncomming(incomming) +{ + CallManager::instance().registerCall(*this); +} + +Call::Call(const Session &session, + const Account &account, + const QString &callId, + const QString &peer, + bool incomming) + : mSessionId(session.id()) + , mAccountId(account.id()) + , mId(callId) + , mPeer(peer) + , mIsIncomming(incomming) +{ + CallManager::instance().registerCall(*this); +} + +bool +Call::isIncomming() +{return mIsIncomming;} + +Request * +Call::answer() +{ + mIsIncomming = false; + std::list< QString> args; + args.push_back(mId); + return Requester::instance().send(mSessionId, "answer", args); +} + +Request * +Call::hangup() +{ + std::list< QString> args; + args.push_back(mId); + return Requester::instance().send(mSessionId, "hangup", args); +} + +Request * +Call::cancel() +{ + std::list< QString> args; + args.push_back(mId); + return Requester::instance().send(mSessionId, "cancel", args); +} + +Request * +Call::hold() +{ + std::list< QString> args; + args.push_back(mId); + return Requester::instance().send(mSessionId, "hold", args); +} + +Request * +Call::unhold() +{ + std::list< QString> args; + args.push_back(mId); + return Requester::instance().send(mSessionId, "unhold", args); +} + +Request * +Call::refuse() +{ + mIsIncomming = false; + std::list< QString> args; + args.push_back(mId); + return Requester::instance().send(mSessionId, "refuse", args); +} + +Request * +Call::notAvailable() +{ + mIsIncomming = false; + std::list< QString> args; + args.push_back(mId); + return Requester::instance().send(mSessionId, "notavailable", args); +} + +Request * +Call::transfer(const QString &to) +{ + std::list< QString> args; + args.push_back(mId); + args.push_back(to); + return Requester::instance().send(mSessionId, "transfer", args); +} + +Request * +Call::sendDtmf(char c) +{ + std::list< QString> args; + args.push_back(mId); + QString s; + s += c; + args.push_back(s); + return Requester::instance().send(mSessionId, "senddtmf", args); +} + diff --git a/src/gui/qt/Call.hpp b/src/gui/qt/Call.hpp new file mode 100644 index 0000000000..d3d626c68e --- /dev/null +++ b/src/gui/qt/Call.hpp @@ -0,0 +1,142 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef SFLPHONEGUI_CALL_H +#define SFLPHONEGUI_CALL_H + +#include <qstring.h> + +class Account; +class Request; +class Session; + +class Call +{ + public: + /** + * A call is automaticaly registered in + * the CallManager. However, a call isn't + * registered when you have a copy constructor. + */ + Call(const QString &sessionId, + const QString &accountId, + const QString &callId, + const QString &destination, + bool incomming = false); + Call(const Session &session, + const Account &account, + const QString &callId, + const QString &destination, + bool incomming = false); + + /** + * This function returns true if the + * call is waiting to be picked up. + */ + bool isIncomming(); + + QString id() const + {return mId;} + + QString peer() const + {return mPeer;} + + /** + * This function will answer the call. + */ + Request *answer(); + + /** + * This function will try to transfer the + * call to the peer. + */ + Request *transfer(const QString &to); + + /** + * This function will hangup on a call. + */ + Request *hangup(); + + /** + * ///TODO need to clarify this function. + */ + Request *cancel(); + + /** + * This function will put the call on hold. + * This *should* stop temporarly the streaming. + */ + Request *hold(); + + /** + * This function will unhold a holding call. + * This *should* restart a stopped streaming. + */ + Request *unhold(); + + /** + * This function refuse and incomming call. + * It means that the phone is ringing but we + * don't want to answer. + */ + Request *refuse(); + + /** + * This function will set this client to be + * not able to receive the call. It means that + * the phone can still ring. But if every client + * sent notavailable, then it will be refused. + */ + Request *notAvailable(); + + + /** + * This function will send a tone to the line. + * This is used if you make a choice when you + * have a voice menu. + */ + Request *sendDtmf(char c); + + private: + + /** + * This is the session id that we belong to. + */ + QString mSessionId; + + /** + * This is the account id that we belong to. + */ + QString mAccountId; + + /** + * This is the unique identifier of the call. + */ + QString mId; + + /** + * This is the destination of the call. + */ + QString mPeer; + + bool mIsIncomming; +}; + +#endif diff --git a/src/gui/qt/CallManager.hpp b/src/gui/qt/CallManager.hpp new file mode 100644 index 0000000000..8eff2b2f68 --- /dev/null +++ b/src/gui/qt/CallManager.hpp @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author : Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __CALL_MANAGER_HPP__ +#define __CALL_MANAGER_HPP__ + +#include "utilspp/Singleton.hpp" +#include "CallManagerImpl.hpp" + +typedef utilspp::SingletonHolder< CallManagerImpl > CallManager; + +#endif + diff --git a/src/gui/qt/CallManagerImpl.cpp b/src/gui/qt/CallManagerImpl.cpp new file mode 100644 index 0000000000..e09a411843 --- /dev/null +++ b/src/gui/qt/CallManagerImpl.cpp @@ -0,0 +1,68 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qobject.h> +#include <stdexcept> + +#include "CallManagerImpl.hpp" +#include "DebugOutput.hpp" + +void +CallManagerImpl::registerCall(const Call &call) +{ + mCalls.insert(std::make_pair(call.id(), call)); +} + +void +CallManagerImpl::unregisterCall(const Call &call) +{ + unregisterCall(call.id()); +} + +void +CallManagerImpl::unregisterCall(const QString &id) +{ + std::map< QString, Call >::iterator pos = mCalls.find(id); + if(pos != mCalls.end()) { + mCalls.erase(pos); + } +} + +bool +CallManagerImpl::exist(const QString &id) +{ + std::map< QString, Call >::iterator pos = mCalls.find(id); + if(pos == mCalls.end()) { + return false; + } + + return true; +} + +Call +CallManagerImpl::getCall(const QString &id) +{ + std::map< QString, Call >::iterator pos = mCalls.find(id); + if(pos == mCalls.end()) { + throw std::runtime_error("Trying to retreive an unregistred call\n"); + } + + return pos->second; +} diff --git a/src/gui/qt/CallManagerImpl.hpp b/src/gui/qt/CallManagerImpl.hpp new file mode 100644 index 0000000000..a7e02aa225 --- /dev/null +++ b/src/gui/qt/CallManagerImpl.hpp @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __CALL_MANAGER_IMPL_HPP__ +#define __CALL_MANAGER_IMPL_HPP__ + +#include <qmutex.h> +#include <qstring.h> +#include <map> + +#include "Call.hpp" + +class CallManagerImpl +{ +public: + void registerCall(const Call &call); + void unregisterCall(const Call &call); + void unregisterCall(const QString &id); + + /** + * Return true if the call is registered. + */ + bool exist(const QString &id); + + /** + * Return the call with the given id. If + * there's no such call it will throw a + * std::runtime_error. + */ + Call getCall(const QString &id); + +private: + std::map< QString, Call > mCalls; +}; + +#endif diff --git a/src/gui/qt/CallStatus.cpp b/src/gui/qt/CallStatus.cpp new file mode 100644 index 0000000000..2ed447d80e --- /dev/null +++ b/src/gui/qt/CallStatus.cpp @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "globals.h" + +#include "CallStatus.hpp" +#include "PhoneLineManager.hpp" + +CallStatus::CallStatus(const QString &code, + const std::list< QString > &args) + : CallRelatedEvent(code, args) +{ + std::list< QString > l = getUnusedArgs(); + if(l.size() >= 3) { + mAccountId = *l.begin(); + l.pop_front(); + mDestination = *l.begin(); + l.pop_front(); + mStatus = *l.begin(); + l.pop_front(); + setUnusedArgs(l); + } +} + +void +CallStatus::execute() +{ + QString id = getCallId(); + if(id.length() > 0) { + DebugOutput::instance() << QObject::tr("%1 status received for call ID: %2.\n") + .arg(mStatus) + .arg(id); + PhoneLineManager::instance().addCall(mAccountId, getCallId(), mDestination, mStatus); + } + else { + DebugOutput::instance() << QObject::tr("Status invalid: %1\n").arg(toString()); + } +} + diff --git a/src/gui/qt/CallStatus.hpp b/src/gui/qt/CallStatus.hpp new file mode 100644 index 0000000000..3b648d0ead --- /dev/null +++ b/src/gui/qt/CallStatus.hpp @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __CALLSTATUS_HPP__ +#define __CALLSTATUS_HPP__ + +#include "Event.hpp" + +class CallStatus : public CallRelatedEvent +{ +public: + CallStatus(const QString &code, + const std::list< QString > &args); + + void execute(); + +protected: + QString mAccountId; + QString mDestination; + QString mStatus; +}; + +#endif + diff --git a/src/gui/qt/CallStatusFactory.hpp b/src/gui/qt/CallStatusFactory.hpp new file mode 100644 index 0000000000..83e467b6ec --- /dev/null +++ b/src/gui/qt/CallStatusFactory.hpp @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __CALLSTATUSFACTORY_HPP__ +#define __CALLSTATUSFACTORY_HPP__ + +#include "EventFactory.hpp" + +typedef utilspp::SingletonHolder< EventFactoryImpl< Event > > CallStatusFactory; + +#endif + diff --git a/src/gui/qt/ConfigurationManager.hpp b/src/gui/qt/ConfigurationManager.hpp new file mode 100644 index 0000000000..1cc5abe819 --- /dev/null +++ b/src/gui/qt/ConfigurationManager.hpp @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author : Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __CONFIGURATION_MANAGER_HPP__ +#define __CONFIGURATION_MANAGER_HPP__ + +#include "utilspp/Singleton.hpp" +#include "ConfigurationManagerImpl.hpp" + +typedef utilspp::SingletonHolder< ConfigurationManagerImpl > ConfigurationManager; + +#endif + diff --git a/src/gui/qt/ConfigurationManagerImpl.cpp b/src/gui/qt/ConfigurationManagerImpl.cpp new file mode 100644 index 0000000000..68d432e963 --- /dev/null +++ b/src/gui/qt/ConfigurationManagerImpl.cpp @@ -0,0 +1,168 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "ConfigurationManagerImpl.hpp" +#include "DebugOutput.hpp" +#include "Session.hpp" +#include "taxidermy/Hunter.hpp" + +ConfigurationManagerImpl::ConfigurationManagerImpl() + : mSession(NULL) +{} + +ConfigurationManagerImpl::~ConfigurationManagerImpl() +{ + delete mSession; +} + +void +ConfigurationManagerImpl::setCurrentSpeakerVolume(unsigned int ) +{ +} + +void +ConfigurationManagerImpl::setCurrentMicrophoneVolume(unsigned int ) +{ +} + +void +ConfigurationManagerImpl::setSession(const Session &session) +{ + mSession = new Session(session); +} + +void +ConfigurationManagerImpl::save() +{ + if(mSession) { + SectionMap::iterator pos = mEntries.begin(); + while(pos != mEntries.end()) { + VariableMap::iterator vpos = pos->second.begin(); + while(vpos != pos->second.end()) { + ConfigEntry entry(vpos->second); + mSession->configSet(entry.section, entry.name, entry.value); + vpos++; + } + + pos++; + } + + mSession->configSave(); + } + else { + DebugOutput::instance() << QObject::tr("ConfigurationManagerImpl::save(): " + "We don't have a valid session.\n"); + } +} + +void +ConfigurationManagerImpl::finishSave() +{ + emit saved(); +} + +void +ConfigurationManagerImpl::add(const ConfigEntry &entry) +{ + mEntries[entry.section][entry.name] = entry; +} + +void +ConfigurationManagerImpl::addAudioDevice(QString index, + QString hostApiName, + QString deviceName) +{ + AudioDevice device; + device.index = index; + device.hostApiName = hostApiName; + device.deviceName = deviceName; + add(device); +} + +void +ConfigurationManagerImpl::add(const AudioDevice &entry) +{ + mAudioDevices.push_back(entry); + emit audioDevicesUpdated(); +} + +void +ConfigurationManagerImpl::addRingtone(QString index, QString filename) +{ + Ringtone tone; + tone.index = index; + tone.filename = filename; + add(tone); +} + + +void +ConfigurationManagerImpl::add(const Ringtone &entry) +{ + mRingtones.push_back(entry); + emit ringtonesUpdated(); +} + +void +ConfigurationManagerImpl::addCodec(QString index, QString codecName) +{ + Codec codec; + codec.index = index; + codec.codecName = codecName; + add(codec); +} + + +void +ConfigurationManagerImpl::add(const Codec &entry) +{ + mCodecs.push_back(entry); + emit codecsUpdated(); +} +void +ConfigurationManagerImpl::set(const QString §ion, + const QString &name, + const QString &value) +{ + SectionMap::iterator pos = mEntries.find(section); + if(pos != mEntries.end()) { + VariableMap::iterator vpos = pos->second.find(name); + if(vpos != pos->second.end()) { + vpos->second.value = value; + } + } +} + +QString +ConfigurationManagerImpl::get(const QString §ion, + const QString &name) +{ + QString value; + SectionMap::iterator pos = mEntries.find(section); + if(pos != mEntries.end()) { + VariableMap::iterator vpos = pos->second.find(name); + if(vpos != pos->second.end()) { + value = vpos->second.value; + } + } + + return value; +} + diff --git a/src/gui/qt/ConfigurationManagerImpl.hpp b/src/gui/qt/ConfigurationManagerImpl.hpp new file mode 100644 index 0000000000..10391f9ad9 --- /dev/null +++ b/src/gui/qt/ConfigurationManagerImpl.hpp @@ -0,0 +1,174 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef __CONFIGURATION_MANAGER_IMPL_HPP__ +#define __CONFIGURATION_MANAGER_IMPL_HPP__ + + +#include <list> +#include <map> +#include <qobject.h> +#include <vector> + +struct AudioDevice +{ +public: + QString index; + QString hostApiName; + QString deviceName; +}; + +struct Ringtone +{ +public: + QString index; + QString filename; +}; + +struct Codec +{ +public: + QString index; + QString codecName; +}; + +/** + * This is the representation of a configuration + * entry. + */ +struct ConfigEntry +{ +public: + ConfigEntry(){} + + ConfigEntry(QString s, + QString n, + QString t, + QString d, + QString v) + { + section = s; + name = n; + type = t; + def = d; + value = v; + } + + QString section; + QString name; + QString type; + QString def; + QString value; +}; + + +class Session; + +class ConfigurationManagerImpl : public QObject +{ + Q_OBJECT + +signals: + void audioDevicesUpdated(); + void ringtonesUpdated(); + void codecsUpdated(); + void updated(); + void saved(); + +public: + ConfigurationManagerImpl(); + ~ConfigurationManagerImpl(); + + /** + * will set the session to use. + */ + void setSession(const Session &session); + + /** + * This function will set the current speaker volume + * to the given percentage. If it's greater than 100 + * it will be set to 100. + */ + void setCurrentSpeakerVolume(unsigned int percentage); + + /** + * This function will set the current microphone volume + * to the given percentage. If it's greater than 100 + * it will be set to 100. + */ + void setCurrentMicrophoneVolume(unsigned int percentage); + + + void set(const QString §ion, + const QString &name, + const QString &value); + + QString get(const QString §ion, + const QString &name); + + void clearAudioDevices() + {mAudioDevices.clear();} + + std::list< AudioDevice > getAudioDevices() + {return mAudioDevices;} + + std::list< Ringtone > getRingtones() + {return mRingtones;} + + std::list< Codec > getCodecs() + {return mCodecs;} + + QStringList getSkins(); + //QString getCurrentSkin(){return QString("metal");} + + void complete() + {emit updated();} + + void save(); + + void finishSave(); + +public slots: + void add(const ConfigEntry &entry); + + void addAudioDevice(QString index, QString hostApiName, QString deviceName); + void add(const AudioDevice &entry); + + void addRingtone(QString index, QString filename); + void add(const Ringtone &entry); + + void addCodec(QString index, QString codecName); + void add(const Codec &entry); + + +private: + typedef std::map< QString, ConfigEntry > VariableMap; + typedef std::map< QString, VariableMap > SectionMap; + SectionMap mEntries; + + std::list< AudioDevice > mAudioDevices; + std::list< Ringtone > mRingtones; + std::list< Codec > mCodecs; + + Session *mSession; +}; + +#endif diff --git a/src/gui/qt/ConfigurationPanel.ui b/src/gui/qt/ConfigurationPanel.ui new file mode 100644 index 0000000000..ae570654b6 --- /dev/null +++ b/src/gui/qt/ConfigurationPanel.ui @@ -0,0 +1,1497 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>ConfigurationPanel</class> +<widget class="QDialog"> + <property name="name"> + <cstring>ConfigurationPanel</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>571</width> + <height>548</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>Configuration panel</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <widget class="QListBox"> + <property name="name"> + <cstring>Menu</cstring> + </property> + <property name="geometry"> + <rect> + <x>11</x> + <y>11</y> + <width>100</width> + <height>484</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="cursor"> + <cursor>13</cursor> + </property> + <property name="currentItem"> + <number>-1</number> + </property> + <property name="selectionMode"> + <enum>Single</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout17</cstring> + </property> + <property name="geometry"> + <rect> + <x>120</x> + <y>10</y> + <width>437</width> + <height>484</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TitleTab</cstring> + </property> + <property name="font"> + <font> + <bold>1</bold> + </font> + </property> + <property name="text"> + <string>Setup signalisation</string> + </property> + </widget> + <widget class="Line"> + <property name="name"> + <cstring>linee2</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QTabWidget"> + <property name="name"> + <cstring>Tab_Signalisations</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>SIPPage</cstring> + </property> + <attribute name="title"> + <string>SIP Authentication</string> + </attribute> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout24</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>410</width> + <height>393</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="title"> + <string></string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0" colspan="3"> + <property name="name"> + <cstring>lblFullName</cstring> + </property> + <property name="text"> + <string>Full name</string> + </property> + </widget> + <widget class="QLineEdit" row="1" column="0" colspan="3"> + <property name="name"> + <cstring>fullName</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLabel" row="2" column="0" colspan="3"> + <property name="name"> + <cstring>lblUserHostPart</cstring> + </property> + <property name="text"> + <string>User address (ie: user@domain.com)</string> + </property> + </widget> + <widget class="QLineEdit" row="3" column="0"> + <property name="name"> + <cstring>userPart</cstring> + </property> + </widget> + <widget class="QLabel" row="3" column="1"> + <property name="name"> + <cstring>lblArobase</cstring> + </property> + <property name="text"> + <string>@</string> + </property> + </widget> + <widget class="QLineEdit" row="3" column="2"> + <property name="name"> + <cstring>hostPart</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="title"> + <string></string> + </property> + <grid> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>lblAuthorizationUsre</cstring> + </property> + <property name="text"> + <string>Authorization user</string> + </property> + </widget> + <widget class="QLineEdit" row="1" column="0"> + <property name="name"> + <cstring>username</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>lblPassword</cstring> + </property> + <property name="text"> + <string>Password</string> + </property> + </widget> + <widget class="QLineEdit" row="3" column="0"> + <property name="name"> + <cstring>password</cstring> + </property> + <property name="echoMode"> + <enum>Password</enum> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>lblProxy</cstring> + </property> + <property name="text"> + <string>SIP proxy</string> + </property> + </widget> + <widget class="QLineEdit" row="5" column="0"> + <property name="name"> + <cstring>sipproxy</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout23</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout19</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>autoregister</cstring> + </property> + <property name="text"> + <string>Auto-register</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>201</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>Register</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Register</string> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer9</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>21</height> + </size> + </property> + </spacer> + </vbox> + </widget> + </vbox> + </widget> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>STUNPage</cstring> + </property> + <attribute name="title"> + <string>STUN</string> + </attribute> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>110</y> + <width>253</width> + <height>100</height> + </rect> + </property> + <property name="title"> + <string>Settings </string> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_5</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>38</y> + <width>229</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>STUN server (address:port)</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>STUNserver</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>60</y> + <width>229</width> + <height>23</height> + </rect> + </property> + </widget> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>stunButtonGroup</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>410</width> + <height>90</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>2</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Use STUN</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>useStunNo</cstring> + </property> + <property name="text"> + <string>No</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>useStunYes</cstring> + </property> + <property name="text"> + <string>Yes</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </vbox> + </widget> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>DTMFPage</cstring> + </property> + <attribute name="title"> + <string>DTMF</string> + </attribute> + <widget class="QGroupBox"> + <property name="name"> + <cstring>SettingsDTMF</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>301</width> + <height>130</height> + </rect> + </property> + <property name="title"> + <string>Settings</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout11</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout10</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>playTones</cstring> + </property> + <property name="text"> + <string>Play tones locally</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>111</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>labelPulseLength</cstring> + </property> + <property name="text"> + <string>Pulse length</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>115</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QSpinBox"> + <property name="name"> + <cstring>pulseLength</cstring> + </property> + <property name="suffix"> + <string> ms</string> + </property> + <property name="maxValue"> + <number>1500</number> + </property> + <property name="minValue"> + <number>10</number> + </property> + <property name="value"> + <number>250</number> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>labelSendDTMF</cstring> + </property> + <property name="text"> + <string>Send DTMF as</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>85</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>SIP INFO</string> + </property> + </item> + <property name="name"> + <cstring>sendDTMFas</cstring> + </property> + <property name="currentItem"> + <number>0</number> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + </grid> + </widget> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>TabPage</cstring> + </property> + <attribute name="title"> + <string>Options</string> + </attribute> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout16_7</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>260</width> + <height>23</height> + </rect> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>labelToneZone_4</cstring> + </property> + <property name="text"> + <string>Zone tone:</string> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>North America</string> + </property> + </item> + <item> + <property name="text"> + <string>France</string> + </property> + </item> + <item> + <property name="text"> + <string>Australia</string> + </property> + </item> + <item> + <property name="text"> + <string>United Kingdom</string> + </property> + </item> + <item> + <property name="text"> + <string>Spain</string> + </property> + </item> + <item> + <property name="text"> + <string>Italy</string> + </property> + </item> + <item> + <property name="text"> + <string>Japan</string> + </property> + </item> + <property name="name"> + <cstring>zoneToneChoice</cstring> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer5_4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>31</width> + <height>21</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </widget> + </widget> + <widget class="QTabWidget"> + <property name="name"> + <cstring>Tab_Audio</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>DriversPage</cstring> + </property> + <attribute name="title"> + <string>Drivers</string> + </attribute> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>DriverChoice</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>410</width> + <height>180</height> + </rect> + </property> + <property name="title"> + <string>Drivers list</string> + </property> + </widget> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>CodecsPage</cstring> + </property> + <attribute name="title"> + <string>Codecs</string> + </attribute> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>CodecsChoice</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>200</width> + <height>157</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Supported codecs</string> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout18</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>20</y> + <width>110</width> + <height>120</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout17</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QComboBox"> + <property name="name"> + <cstring>codec1</cstring> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>codec2</cstring> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>codec3</cstring> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget" row="0" column="1"> + <property name="name"> + <cstring>layout18</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_4</cstring> + </property> + <property name="text"> + <string>1</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_4_2</cstring> + </property> + <property name="text"> + <string>2</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_4_3</cstring> + </property> + <property name="text"> + <string>3</string> + </property> + </widget> + </vbox> + </widget> + </grid> + </widget> + </widget> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>RingPage</cstring> + </property> + <attribute name="title"> + <string>Ringtones</string> + </attribute> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox5</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>410</width> + <height>62</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Ringtones</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QComboBox" row="0" column="0"> + <property name="name"> + <cstring>ringsChoice</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </grid> + </widget> + </widget> + </widget> + <widget class="QTabWidget"> + <property name="name"> + <cstring>Tab_Preferences</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>DriversPage</cstring> + </property> + <attribute name="title"> + <string>Themes</string> + </attribute> + <widget class="QComboBox"> + <property name="name"> + <cstring>SkinChoice</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="geometry"> + <rect> + <x>12</x> + <y>42</y> + <width>110</width> + <height>27</height> + </rect> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonApplySkin</cstring> + </property> + <property name="geometry"> + <rect> + <x>136</x> + <y>40</y> + <width>80</width> + <height>32</height> + </rect> + </property> + <property name="text"> + <string>&Apply</string> + </property> + <property name="accel"> + <string>Alt+A</string> + </property> + </widget> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>TabPage</cstring> + </property> + <attribute name="title"> + <string>Options</string> + </attribute> + </widget> + </widget> + <widget class="QTabWidget"> + <property name="name"> + <cstring>Tab_About</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>DriversPage</cstring> + </property> + <attribute name="title"> + <string>About SFLPhone</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTabWidget" row="0" column="0"> + <property name="name"> + <cstring>tabWidget6</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Tab 1</string> + </attribute> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Tab 2</string> + </attribute> + </widget> + </widget> + <widget class="QTextEdit" row="0" column="0"> + <property name="name"> + <cstring>textEdit1</cstring> + </property> + </widget> + <widget class="QFrame" row="0" column="0"> + <property name="name"> + <cstring>frame4</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="paletteBackgroundColor"> + <color> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="0" column="2"> + <property name="name"> + <cstring>spacer22</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer row="0" column="0"> + <property name="name"> + <cstring>spacer23</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer row="1" column="1"> + <property name="name"> + <cstring>spacer9_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><p align="center"> +Copyright (C) 2004-2005 Savoir-faire Linux inc.<br /> +Jean-Philippe Barrette-LaPierre <br> +&nbsp;&nbsp;&nbsp;&lt;jean-philippe.barrette-lapierre@savoirfairelinux.com&gt;<br /> +Laurielle LEA <br/> &nbsp;&nbsp;&nbsp;&lt;laurielle.lea@savoirfairelinux.com&gt;<br /> +Yan Morin <br/>&nbsp;&nbsp;&nbsp;&lt;yan.morin@savoirfairelinux.com&gt;<br /> +Jérome Oufella <br/> &nbsp;&nbsp;&nbsp;&lt;jerome.oufella@savoirfairelinux.com&gt;<br /> + +<br />SFLphone-qt 0.6.2 is released under the General Public License. For more information, see http://www.sflphone.org</p></string> + </property> + </widget> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>pixmapLabel1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="paletteBackgroundColor"> + <color> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </property> + <property name="pixmap"> + <pixmap>image0</pixmap> + </property> + <property name="scaledContents"> + <bool>true</bool> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>CodecsPage</cstring> + </property> + <attribute name="title"> + <string>About Savoir-faire Linux inc.</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QFrame" row="0" column="0"> + <property name="name"> + <cstring>frame12</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="paletteBackgroundColor"> + <color> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="2" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><p align="center">Website: http://www.savoirfairelinux.com<br><br> +5505, Saint-Laurent - bureau 3030<br> +Montreal, Quebec H2T 1S6</p></string> + </property> + </widget> + <spacer row="1" column="1"> + <property name="name"> + <cstring>spacer19</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + <spacer row="0" column="0"> + <property name="name"> + <cstring>spacer21</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>pixmapLabel2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="pixmap"> + <pixmap>image1</pixmap> + </property> + <property name="scaledContents"> + <bool>true</bool> + </property> + </widget> + <spacer row="0" column="2"> + <property name="name"> + <cstring>spacer20</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> + </widget> + </grid> + </widget> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout19</cstring> + </property> + <property name="geometry"> + <rect> + <x>11</x> + <y>501</y> + <width>543</width> + <height>36</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="Line"> + <property name="name"> + <cstring>linee2</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout28</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <spacer> + <property name="name"> + <cstring>Horizontal Spacing2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>160</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonOk</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>2</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="accel"> + <string>Alt+O</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonCancel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>2</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + <property name="accel"> + <string>F, Backspace</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> +</widget> +<images> + <image name="image0"> + <data format="XPM.GZ" length="58862">789ced5d596fe3b8b27e9f5f114cbd0d0eea6475625cdc878eb3b4b34ca72799e9745f9c07c74b76c776363b07e7bfdf629194488ad49249e4f40151109292488a923e7dac85a2fff9dbc2e9d1e1c26ffffce5fea1f370d95de85e74260bbff51e6f6f67fff7affffdf72fbfae2c2d2f34971696165717967ffdc72fbfe21f0bdd05682c37d61a52ffcc7a87f40eebbb4a6f2a7d47e93da57f17fafa4aa3b7be2274e8487d7d49eab8a4f43575fc96f533d2cf58df547a53e953a5f794fe22f48d95f5de866caf2df58d25a9c34ce96beaf8b9d4cf96cf56f9f890f5333a2edb1b2bbd29757c547a4f1d1f495dd7c78b44efb13e507a43e9db426fae6ef49af27c7da93797943e50fa9ad4f145ea49fd65a577947ea8f5ee1ad7df557a5f1e872dadcbe3f8c47a97daefb2fea0f4a6d2ef95de53faa5d4757de849bdbbacf496d03babcd5e47f6ff52ea9d25a583d2d7a48e7da927f59f125d5ecf27a537947ec47a97eacbfe4c94de51fab1d2fb528767a927f5af94de913a74b5de93e7df577a5f955f14fad96aa7af9ee758eac9f36d28bda1f0b22775dd1e9e28bdaff403a9f79695bece7a2f799e23a5ebe7f9ac74f5fc7045eaba3e7c4af43e1f5f557a43eac0f8eaae25cffb4eeafa7ee354e90da5f7a4aeebe3b5d23baa3d7e3fba3d7d3fe14ee9ea7ee250e9eafec195d4757dfc5debfd06eb6b4aefabf62fb42e8fc367a9f79795ceef5b6f2db99f33a927f7734fe90da57f937a52ff20d1657fba4a6fa8fefc99e8f238bf2fd43b7d3f51e9fa7a6e95aefa8f9b52d7f5e14ce91dd5de86d0fb0d7d7df855eaba7fd854baea0fec285dd587b6d607f2f8b5d2fbaafd2f5a57c7f97dee27fdc153a5ebf6264ad7f5ffd2baac8f37521f2c2bfd4ce90da5ff10fa20391fee4b3d29df52ba2edf49f4019fff46e91da533df0c06fa3882d2d5f1af0f4a1f683d4a94fa24622e4add123117a56e89988b52b744cc45a95b22e6a2d42d117351ea9688b928754bc45c94ba25622e4add123117a56e89988b52b744cc45a95b22e6a2d42d7f177308d821399bf77544f979e4b598c32ef6b08f033cc70bb55de2155ee3cdbcafe8e30bdee210ef7084639ce03d3ee0233ed1df09e9cf38c519decebb87ef2bd53147ac768d2f8cb601612dfbf7136ecefbaa3ea2600bb70855dbb883bbf8b960dbc5366171847bb83fef7ebfbd54c51c1e58dc16da0e3f0eeef81df91dbfbc4bdbfb848b23622d282cf99570f4c7abb6e379dfc1b7962a98c31b1a3ffddce6fb7b52aac53f091107344a5ff2d87c42e8f8eb2daf0fbf25fd7973d4e1293392e0a5eff8a3a0ec6221b785b6a5b7eef7bca53ce6e8e915f39bbd2de7f916c43f57c17a2b7ebb903c966f6447ae166c6b29be08cdbaddde5bdf3b6c187c342a28bbe4e1b0255c278edcc0267e05c42d00e8f8b80ef0ad7b3e5f298b39465c96cb06849b2b42c8359ce1267433c797b1e36d0d88db2e0ab8f2c41db108a56539f602bfa9f324fbe1cd31077d838f724740ea4786bf60e02b07e7597b0fcedfbae7f3957298f372dc00d7ac327f911597e5ac818fb108a7699915dc14c8c40e9cc105f48cba874ead9ea7fdd0c67da3676df8d56f7defc8df4cb928b7751a855deeea602b507694e1bac5b7eef97ca50ce6f08b974baecd32c47321cec93c0db2e0521f37c38364e3ad32838ae3dfac73749df69709bb3d204e931bc915fd774dffabbec14d5e3ffeae900f9a72513ee6006e1d9edb0a9786a1c373776fddf3f94a29cc2dfbb8c4ba4b6730cae19c15abb52fc9fee073a267744163ab331a1242cd7657a13016581fcf6151d99151760727b9656fd9fa53e561f8d6fd9eb714638ec63eafdd649559ceb7afe0dadb5ec5f8b1652f96b2ce98e7743fde97e7c685a587e42734b3f13698900771ef29dfa211f9166790d766618c46956bc2234ee9fca76f7d0f5e234598a3912ec45f3725caa80d9e8c7bfca4f62f57ed2b3c57e5ac6a3c87fb70477e64533c49dcc7198ef101a6f81d66788477d9676ff1dc1fd2d2a7e7fa0c973084195c12b70523bad4b3676a7da6f90c3a30a61acd40e91f7847e567844260940e71421ecc928e1e877009f7e40bbfa49c293816c80dae7ae7df568a30079fcac4df380b96ef4b265137b6d5c4fe4f55fb6ad87307256b54b0e70861a94fd9f1c6ca1c5bdee439e6ba4e12af4bda8147efb9a6b0e9cf3f402bcb4584c5cf057ddbf58dd6701eb80eb204ca32e47b4821cf0d82fc3548fb4dcfd66bf319db956a2fe144c8b1a2037d49ec39b82859a302cf116b14e604888b8c676bf35cb0ceb6739e0d62a6dc3a84310311706ff154f83cb6853d8171ee39a64551ecf7937ccc4149eee2d859418e425bfc894ffa37ecb9b29833edb97c8cc343b9bc00f99f498cc3e539ff465c6322085d2ef46e064e7156a65fcca98955483ed8b0b04e7b5e5c5780b96e0e772dbb1126f20ef2b84e656089add27c43a5ab4eed3928392e97e7395f3e1436c9f619e13d8f50e9fe84e9caf11c6d897f41c8dec91cff4ee36cb64edab359e9dc6ce2e11253da1cb8497bc66401dad7f72131c7fe68c817ddf194ff421e4288eb5655995563ff7295b900863d57d287b0ecb9c3dc92599e3347d16d63ffae1e95b23c0703c2e83159edf6fe84b518a5d639a4f5c6734edaceb199aa93e1397811ef029dcbe52e957f33f2c09f79144d7c06f2904d3bf27b282efdbe92873908fba397e18c395c046cc0849bac5cc33969d7e5f2ef567ceeba548dd7f39ce32fc038cb412ecfe9d82db6c0e226d00c3fb4b8a7a351a5fbca2832b849ed77788ed84af11379d98e1da86a3c18fb3fdb769b7d9daead598fe4610ebf0438ab2036a66c3bb75e12d123241c7a8ef7b1879b79715e279fbb92df0bae61c6e772633336cfd93618f779cb3caef6d93c67645c9969b2e56d2ef5cc0ae051362dc3fce4f09cc54d60e571a1aff6764c4ecc9c636a5c67e6681d928bb96e96af60b7242765e78c185164c2c20a86e6e1898cd6375f9b467c4ee57269cf09b1a42d9be96c1693e7f27d0887e71a9eb34f8de3724434796ed78ec5391cc8c74c5b0ebc36059c5b9cc628b679ce9e1940bd36cb735c86fc629b17ad5929ecc398c7e71025ce1d5bcf325c5421a606570e9739f32838bf15f6750fb3a36726df1afeab50f76a7bce1335b5388547c5bc3c04581c28222c840593af02790b93a3a41de8f09c937b25de73cb8f1c3b8fd80cef69ef049f4c8e53dbccdf8ff7945c9edb7478a56214173edbf5bde7001ac1d788ad2e3dbce7ccb374f2ad79db4dd27aba2f17738e9de3cb45ad1bfcf0cc7bcc7925ce1be5d85a6453c1a3c55781f94966ec0ea6bcc7b6e79cecabe5f34a9e9b94f673c5f6fc1628aa26b93cd7b6b8a354ae8afcd6d574ae0878edb990e00d95bfb238cb9a7f97999f774863ab98a3796d6e84f4c4267c9d3d07de397f8c22cd5b6ced59f69c930720567379cea8af6d35cf3dc8f4c3e1b90da757e30ccfdd67b82c67f3e749de577279cef65bd3b9b7c44df464fd3697f4493fe9a33c37d3f15bf385ce7a62d88f8615e6d873d725be427815cff96d2df23a537e38e23da6cde662ceb60f7f64e6c505ec28b8346d446ec9e63907ab561f183fe4d796e5b85d7a6be610a32b88cfa5398313b56713b59de68d3d305e64fcaec7333121c9af96f0339356560dae4bfc34d39e2b9789b0ecb9f27eab27f2e8f014fb9c16cfb9b195877c9e0bcd37b7da6cf31e8be7dc6cbe555ef2dc83cd6564cd1d1147cf5c216fe263c68493f9bc623612f9142f066f9c786b98b9089e73492894ba971773ceece42fac7c6bc95cadc573b963bbc34b9ef920786c1c67abaa22cfd97c159887697d3721f754e4393cb2ec46af9d305f29c0dcb5b68792586f9abff4320d5c383ee441e29b56fad69ff854b7b39ab49dda732539d3b2e7cef3de6b87973c2c0426dfb0556571cc716e7b82e79a165f79470998581cb5ce67a9ca730dab8dc2797df54b01e63a094f64e36dde6f02c907f5fb92157d5e6c2575137e34f2adaf9957720139b90bc76fcde484a83fd9785b259e7338cc6bd1d9795299d7a8cc73b7561b7e0b08e6397bb370fedc5e300ee6650d62466f79a8b8a289f18d57ea8526f65cd9d62c7bee22ef8b5b273eb7eb8eae3831b84667a52ad9733cea99e7c85eb39527d57da8ca734e1ee2366b27e0a2884e136fcf213627a4107367c118981f7327deb2b93ea3b79d6b6d131afbd2f85cc9595036cfe5f1a39b6fd579247517d0e21a9d4bafca734de71c1607e186fd0dace6daaa3ca7a2d7693b632b5b36219426b6dec7cbf1ababfa1488f5fba3584f5e4eec5a2d7e29c20c8d6487b23e18350d7baee437f98e3d27da7bc26bfe4aec0c76f026b5313df34a1e93f9235bc416296725b9d86af61cd77062678487a9980bcf2b99d8f3eabeeb79ead5790ef7ed6f64a9f777c4a12d7a73d6ad3cc72eeebd359eca4809cc75d03f4fe44f4fd91b1f278215eb861ecab973413f965a39d4fc68bda3697cae24e65c9ef36df024d8cfbf9e08bc40dfcab38a2dc9c556e539f12e79e7cae5e607aaf31cc7654a9c43e639ea9752df1afee9e52e8f756ac5d5923cab3d57c498537268e62cd4d18ecafecbfa16b68cf85ce9b547f025688f5a9c5d7a9ef0d8988d6bd671fc43e215b3debeb17fa9c479ccb97b95798ef717ae8f42e89fd3ecf492dff11f7839c2f10369b4cae44c61e4ceedc41bd8b2ca5c72066b8dc6bc7dec9bf1347b44b66276a5a39999b928be6d10e2b90cefb5cc33e3c4389659338e9ea93e66dd01f12d56ee7976ecd89df33d843b37fbd8386665897196c7a9e4417cd0ef218c2b58f172841127232bed30cb21bed9c41cc53bcce59e174260c6e6c3dfd5f10a1e49609d15fbef75a9ef2176325fd3fc20ab4b1e6b7bce7cac8e7dcfe6f3f1ab9527357dd5a32c16f029e1a6ec9a08a9afbbebe662bf8a6fd9be67cf43e79e8b1da7a5c2ba4c2b7e8e202611ab21f9befbbac89b794e185dc1cb6c7be4b3acf96b243c7a55e50af10b5c65e6d8a5f24d62db89cf6d8ad506f116ce0939c46770e7fff29438eb0e4710f2e167b01d5ef781fcd4291e93bdb8091db21bc70070e79bcfc2e74142cfc8df07f2b7ee704cfdf0f7615f7c718b47d4fe0c0506a7f3febab5e2fa73df8cfc6be15ff2154a45d1e89e7dc12e1c10a20af334342e1f54cba1951587e7d6dfe31c51a4545b67932cfcb273d856e77d65d5c4b1e7fecb57f49daf545f4f18ce3cebcc59f3e4b057cc581f4d2c9efb3ecfafdcfffbe575eba613dfadaa58b1c96dcb7812b2c53eba58f3e7e6f265cacf254994fb156b6cffbddf87c01659619bbcc666096bec230b790c29cfcdbd37957b7f1b9a1bf54ee79b605bcc3026ff7b884fc15253ff4c82f83b385ae025b1e77e8a95cac9537dd4cf148f0803019ff75dcedda7bbb52efa407f3d7122eed30f98fa675245cc6949e69ded64e35c1f51a08f6d9d8703a0ff6bf47b08ed7c6e62b2761073b774ccfbf646cca5c22b03ce7e8e5f01c12631db4b92d53f224ea9317b8adb74be06af36360dadb543e3ee4be4b9aa8220a2baf82c249d394c96df3eaf8ad8247c9a6b81006ee008c5bccb75f5053e582b324d6cfe34d6779af1d7a723dc4a66ac00b5b108e7380cc589517c952884bf06123c074311b9a636c4b70fd64a50740d47b84eef53c1db04f738c6276a690cad74bd46c2ce3936685ba7f6f5fcaa323c774ac7bcbf60103117161abd8e047a080153fdcee20f7a26e24edf132a1e04d7c84c83989706537af6e2c91fd3336b094b3bcd55c13d3dc9699a3d23dc3e0a1c93d5d3a2273862643cc240cdeedc127692380fb5ef99274f3d7a54fd78e49537c56a9a6dfebda60798d179fa12a9544eac43774c489ca2f82e312707c1f938d9c63db5a1381487b84d75c53b764af7635baf6020ed39be2f219e8310f746cc85c5e405badb6da103f38bcea0121bb465665d7872aebf4b8c933c0f40ae97cc04854769f513e2da3ac34a3ca34ac09d6431f20a037379457d3ece7599e7668a5d9b023bb28764a3b6d3160889399683b8428d4a14efceb6ea53bab2a5e895fc46a304cf718b5e8c47cc95131ecbf6388ed74e5732a7777906721d89470fe6c8e6d2775da09339418f4e13815562b7a9594bd86522064123aae0b87e78ee07f1a4e04048eb19ebe22d4aeb9d38746622826c84b66f25163ec69c9a9ffbc73d7d8d65ec3931c3c0bf3f62ae8c306371448a79cef8f681ac37f915ea3a3353c35979eb51e7f84539168dc16dc144b2969e1387fb0223e249499ecbff5d0818a4f612fbad49691a0fd9cee335eddae96a13c2560bc51e39da92fb8d188fad8a87cbf15c287a1331972fbc7afabde4288101c173e69a21642bb5d53aeb6c0d11f7b4d2df39c4b1b4e8041f12beee68ec92df729dca919af889ed3042e494acf47b14489ae9b857becd0f2de2448d6830ed3ee6e24bf9a6703bf41fa1f888da7e0afd2e19db0ea17b704a0c3911f6a8b01f794f097b2e2c117321c1167b09fcf536bde3438939e639e38b6ec154fa7fb27deea43f49a5e52a3a5bd25aa367ced8a3b148f2c4a2fcc2465873f42cd14597e4b982fedda74cc83c675a9fcc73b0adbcd912d11fb6e63c5fe4d01508bbe007db78e2ad929e45299e0b49c45c48c4334d474acef69c2b9e33ec7ab6d2adf71c26621c250e427e4ec2b34cd0c156d8808f4b5d708767652469cf15f58fb84dfb32c29e4b7a21ceca3c37947fcb5e6d766c657b33b100c5fb26cb94b3e7421231e717810ecbba9f04786e94c58688a7249ee391b2e3b46fda521ea9f47685e5e5fb6587923c67d973e6ac7969cf9d9a9e72416b23ee97b326077be3497e83af3df2dcbb094cf819682ff394b5a987e746ca9e33c625b6a75ea4b720d0435c90c6e59e9903d3b89df00492f9bf34864ba40ec379cca4ec84da51dfae727c2ec3733c86bfa4ab7d91b5300dfa98fb6caf6d2719dc0deaa988eebda416204764c6b2d7ca9e1be6d97310f855b388b990f00828be09ddc031fb93722685e00e234a4b969a8c9534e8dd5f17bf8e04d2a6532312790f633342c1f113834f84374825d6a9ddafb00d331561c6222f52fbd26a55b2a30ccfc9d8728bfde545dc00b16eec76deec059cb1cd3aa41a138ef08937e996e37e77e25de0b743c70f5b9263a5671c686f3fe621aa0bee894c02bdef7b34aaece9cc8fbd8616dd5995d1a2e313fe052f61bf19712ef1bcac1a5fed118cd8846a127300e156b10c79230d7745cdac48bb51b02e21d62a0d8f464e6e28fa457d1a17fdde35e1f252bc5d847cd01904eafdb6f88e82aeee2b217028475a7a0ff95706443fc3bf688c81bc47c4dccf2c345abef91783ef3fc721622e4add123117a56e89988b52b744cc45a95b22e6a2d42d117351ea9688b928754bc45c94ba25622e4add123117a56e89988b52b744cc45a95b22e6a2d42d117351ea9688b928754bc45c94ba25622e4add123117a56e89988b52b744cc45a95b7efdcffffcf2ff6d14cd7e</data> + </image> + <image name="image1"> + <data format="XPM.GZ" length="68046">789ced7d5973eb38b2e67bff8a8ac65bc704aef62526e6c1b2655b5e655b5e27e6012b49efbb2ddf98ff3e496482a224522665d739a77b5c1951559f052480c487446221f95ffffaeb6cb8fbd7bffeeb1f4fcfe239527fa9503cfef52ffd727333fedfffe77ffdf73ffe59afd6feea56ff6ab53b7fd5fef93ffef1cf90ffa5fe62ad8aa88a6e8c83c0e1a6a80b1563bde6b0111d5989b1b50e5bd111d6fd7e47b82bab4e9f242c65c3a5bf8c71bbe2d3ab178f49dfa6c355f8ddc498dd27d8a53723c2a4dfd6138cf50f082bd98cb174ed69d7e077a79f3d385cf7d8ae3adc1082eabbe2700bb0fb3df820acb1fec10d61235b0e1f24b8edea5775b80ded75fa82cd04d79dfeaec3d01a4c6f9f1dee26fadf11cbaa143116cebe6dd1aeb5b17d4f8821bdc3914eb0d31f840976fa4c40d8a03dc211618b3840fb43eba5eb6f317058b6eb6da78fdd21067bbaf644970976e51b41d8a23dd8196259911da70fcb57ed461bdbf786d8d7df7c2418ebbf42d860fdc31a618b980d1dd6ed661bdbd3439ce8bb254ced13c661d36eb55dfd84e36fdbb6e11fc78f27c29db6ab6f887cb350beab8fbe460ced71f9a5245cc5fe93ae7e9d8acf2ffa84bb6d1c3f1162c8efeac35e128cfc39235c437b057b0976f999e357a7eaf5294358b41d3fcc2a62682ff2eb3dc168af53c4509ec3a2e970cde757ef84655bbaf67611fbfa062dc255ac6fb44298ea2b1c1f3a759f5fdc12566de72f827bc4be7c799960d4df275c257e3e10aea17df507e13ada4339fb771ac000eddaf78ad8ebd3f784499f584930dadba727fd668d709dec6f093724d6bf4bb82d9d3fb23dc21de5fc837a74b8090c73bf73b467d397afb708d7b07cf344b881e33be8116e49d71e7b40b8abdc7893cebf755ac050e7fff81162afcfea04bbf6084eb88e386c24d8b54fbe11a6f285f34f9db6d7afb0fded4ea5e3dac72f10fbf2f898701db1784cb02b4f350837b0bf8c4f4fed511d873b5ebfb8275cedb8df39b6b7e3f5458f843b687f739360acaff32f9daecfafb608d73ace1fb010b1d7c7b70937a8bf7708b7a4e3af6c3b2c3af58e1b4fea04b14f1fdd136e62fbec5d829d3dd92361af0ffb57761a1dc77f8ef697901efb633dc1e87f4f09b7910f6cdf61d56976d07f30c43ebddc20dc421cde11eea2bd3496af3bad0efa2ffc5d437a575fbd4bb88df58d5e087790ff6687b0203e62fb0c3004fbbb4d18fe71f6c0f10ab321eab7db0976fa830bc202c78f1e11560ae7b3b704e3fcd527ac956bbfba72d8faf2c43ae16ec7b55f0bc4be3ce9fc65b7e27f1755c21050b8dfd710437b5d7af69660d77ee1fc5fb7ead39b016148e0fa730731d8dba5673ac1aeffc23dc2d4be3024ac15f2cbd9ab5bf3fa34eaaff9fcd1156141fa2a84ad72fda99cffefd68121189fed13d61d979e6f21f6f9ed4982911f1dc2543fd324acb1bff5b1c30daf4fad13361df47758ff86d767df084bc4e1056185fd2db0bca6cfaf6e09db8e1bcf4c2186fc18efbd12a6fce13a61aa9f3d256cd09ec6f9bf6ecbeb332b88bb952e968fed6f4985fac34b8f51bfd9204cfa05f667dbe7971dc2d5aefbdd3c23f6f9f92b614dfa2e095be47384f56fab0af1d98d672067adebec1fa03d3a3ebf6e2618db3b246c68bcdc20067d38bfec13ae2a8c4f90bfdd6ebdebec63df11437e8ce702c4aa86e905b65f741b5d8cbfb07ce1d3f34a8291cf02319487f1c107e11a6279e8b0ec36bb381f3f20067bb8fc364c30f61fda5b427b305ebc244ced892ce19a72e35fbf136e2a1cafc877053d8ef3d53962d087ed5f235cc7fcccf997ae861ec5f6370883c370f947887d7dd813e12af9a72e61af8ff2ab96c2f182bf1baf4f22bf8dcfafb0bf2cf410c68b686fb00ef2233c235c477b868f09467b30c24d85f38f6b9fa8400f3acc0788bd3ebe9b60d4b74398f4070f84495f5021dc26fb3abe892af428fabf087192df106e2a8c5f9b8485c6f9d9b547d4a0879c3ed527acbbe8ef2462af8f3d136e607bc301e116d64f617beb6061f4472f887d7a7544b889fda39e09b7b07ecaf967d1f0f9c52a61db457f748dd8e70f0f09537e4bf9bd7d4c9bb0d0e86f3e084bedf8ae5dbc259a5ebfc6fc4d5111e83f2e1127e545843ba8df7a4cfa14d6a705eb751c9f847dfd84f31710ecd7048ed713c449fbeb84db684f53230c2184cb5f4930c6c38ab0c2f6055784b5c6f181e577445db8f126ef117bfdfa817087ca538415b687a1fdbba221305e0a11fbfa9863c2945eb9784608b020f21beb23805e2e7df89c6057ff708db05438ff397f22a4cf2fba845b02f93c42ecf3b373c252213f9c3f170a2cecf8c6b07ca5048e7f1311d6c87fe3e27ba1c142e82f38629f3eba262c115bb497d6158dfe14eb67c042aeff38a637be3dc13161ea1ff1445823b62b887515f529b4af050bbafe08b7112b85fac26a825d7b851b4fb20216c278e510b1ff3d6810d688cd1d6183e5b33a62688fb3b7dd205cd3383e1d5f64152c8ae3e99030acf05d7b03c45ebf7df118f5eb3a61ab31be72fe4ad67c7e7549d8e0fe52b885d8d7cf0609c6fda00fc216b16e2518c7b34c30ce2fd8fe1ad8d7b52f7a265c437b5b93605cdf6e2718dbeff820ebbe7efa80b0a5fdb257c4be7efc8630d52f8a107bfdaa45b8a171bcbbf12c1b893ed41faf9f5dfba301e244df43825d7be51562df3e7b94606cdf3ee13a962fb17f9a5ebf1a12aee27e12c3fa36810f38febb849b1ae373c74f19af6fd17f61fe16a477f6e62b84ab8835dabfedd3eb27c275dc1fe1d81f6d9f3ed0846bd81ef94eb88eed09b60937b03d419b704b23ff5d7c2b3b5ebf1e126ed0fe15eaef4079e8cf2ce11a62db264cf68a9e08b735c6f3ce5fcbaed7a739e126ed9fe0f8e87a7d7a35c1185f62fd844fcff608b768ff00ed2da07cec4f45b881ed8f04e116f607c3f11aaf4fb1be387ea4b7176f10a6fc612bc1185f217f145808fd1f8e37e5d307bb84a9fdccad5fa58616e37c8bedd75e1fdf23dc44cc2e08b7703c9933c21decaf4012161afd19fa27588fd27ecc3a62d087f9cf0993bea84fb88dfa4c48b8ab717d564f30ae6fd05e162c86f3a922ac70bda8b0bfadd72f6f0993fe7095b034387e1c1f5525c92f086b5cdff14dc4901fe3c967c2d45eedc6a3aafaf4ea94b0a1f5da0d629fdfb40877b0ff831ae12ef68f70fda56a3e3fab20f6e92523aca8fe6ebcab3a58c0d547be22f6e9b921dcc5f6cb3e6181f6d5ce9e10dd55687df44ab84aeb9333c43e3fab2518e7ff3161d26776096b83f184e31b445fa4cf5c10aee17a85df2286fcc8cf2a6189fa6425c1b8bebc22ecdb8fe5b7bc3e31225cc7f5093f46ecf5471b842562b34ed8607dc5598271fde4c623445ba44f56093768bd3244eceb6b1e092be4ab6e13b606d7bfce9f43f445f9f519e126ae2722e45b07f263fcf29a608c474e096bb447b0ef31dac3387f08d115e9532b845b18ff73ec8f6ea26f8330e9b37dc206f5856f884d05ed13ac2518f79fddfc06c1451bd70716eb2bbc3ef346d8a23d03e4af305583f5433e49b000fa8723c4da607e7ee031d6275845ecf30bccafa085383eeb887d7a63085bc41ac76f1c1fe2f87842ecfb4735119b1aea0f3b84eb06d74fad04e37e37f2338e17717c058415c6b71cfbdf78fd01470cf6c3f91af9697d7a8b7cb6dede518f7015ed179e2718e7c357c2543f7b91609c1f9c3fd571fc88f1ef0031e4c7f95f2518e3bb63c23eff05e10662ad138cf38de3abae428b91ef06b1d717dc11ae219622c1b87fe37f6f60fdcd15e126ea57a81fe2418a7f0927fa2618f5ad11ae63ff055b845b06e335177fc1ec5ac1f854bd11ae627c667711437eb4ef71829d3e734d98f431b7ded70d9f5f9d13ae61fcc5b17d0d9f5faf106e10bf2ce136ead38e4f305b527e7d4eb88ef195d946ecf3739d609cef07847d7bb17e2d9f5f87841b142fa1bd5b606fe44f8d700bed2f1d1f75dba7d701e126c537b788213ff285116e21b61eb70dee2f20df3a5003ec6ffcbde3d3eb31e18ec178f088701731c3f677a106b87f718018f4637df1770125205e45ec7fb79d043bfb44fef70ee2604c1896782ebff3afe0ddbb387f877dc43ebd6d12a6fa9977c294dfd4138cfedc1096884d27c16efc48e49bf2e5c9066181f3b9467b29281ff11be12ee1f504bbfad847c2549ff088b02f5f1256583e437e6a6831da1bdba3bdfe684cd8a777f134786b85f329477b1a280fe3b367c212cbb7878495c17805cbb35022fa27e4bff5f9f93d61ca1f9c2718e3434698ea63fdef9af43b6c2a50433cefea21f6faf40e6185fac40b6163717fdaf93f53851aa2ff6920f6e9a377c206cb0b373ca6fc6ebd0bdea982f38f8c0857d1ff734598f4d92a618ded096f138ced71f6066f42f9c51ee11afa732608537ee37fa7fa29e7dfc05b507ab947b88efed48e081bcccff7138cf1c13d625bb158beeb4f18fd945f8e0837d07ff22e619f7f1d31e4c778cb8d5718fd945e0e0937c9bf55095bb467c411fbfccaf93f13fb1bdccff198d2f307c4901ee7ff1bc255acbfae2518e7ab6bc235c4519860dc8f73fed57492f27609b7d17f71ec9f8eb74f68087bfd1dc2a44fbb78ce747d7ed123dc417fc5914f5d5f5f2e138cfbfd6784499f443e0b9f5f5f12ee92bf3a460ce9f17cea25c158bf2ae13aea53680fe9f3b323c202fd0143fdd2e737f784eb16e737ca6f1b88a59b8f4dec7fd03f617d15a4c778fd34c1185f9f2418e79b16e186c5780cc757ec8fd0bf60ff6a9f3f3822dc202c083731bfc0fa19d080ebbd26625f5f734a98d2eb7e82717d8cfd6ffd78b1d83e0bbf637d25e116a60f77138cf1931b2fb6021a707c9f22f67ce5823095cf2ce11662fb9460d4bf49b88dfa95eb4f600be95303c2c4a74811267dbc93608c6f1f08933ee67fef58dc0f77f32ff43ee9934dc2c42ffd4898f4c907c26dc4c1907007f50b672fe83dca6faf09537a5e4b30d6a74d98ea23d13e0dcfa7f09430e90f5f128ce91d3fc0bac40f7d4b987ee72dc25d6aef6b8291ffaebfa175d4df22224cf60cf709537e354a30aeff4f080bc4f226c1b89e40fbb6bd3e51274cf6608630e50f9e128cf193222c110bb457c7e797cf84c93efa8a30e5679230e58f6e138ceb75ac6fd7e7976784a9bdfc9130e597d709c6f12a082bc4c2f903289df2eb8830b58f33c2943e6c2718e76fe7dfe2d2b03cbe4e98d2eb6a8231fd98b046cc102b9f9eaf11a6dfc55b8271fdfc48d82066681f9da41709c6f9744898d273e74f6284589c2718f7d3de095bc407d85f76827fe4477e9dfc70ee477eb5fc70ee477eb5fc70ee477eb5fc70ee477eb57c3fe738e3824baeb8e6865b1ef090472097fc8a5ff31b7ecbeff83d7f8034ec77b7fd477e8f7c27e7f82330ed893ff317fecadff87bae8cf907a459e13dbecad77eb7057ee457cb77708ef7f93adfe09b7cc0b716726d56b6f90edfe57b7c1f7ce3f0775be2477e957c9573c037c90ff8213f2ac1b57919f1637ef2e3f3feff90af700ef876cacff839cc955fe11bca05af80c7abf2feefb6c88ffcddb22ce7f890d780235bbcfe0d7c9bc4793bbcc19b3ffeee3f5b96e31c6ff136f8b7afcda779f20abeb3f3bbedf2237f9f2cc339de659cb1bf856f7e9e0d99f89965ff53a52ce798e46da6fe260f379123a6f92d33bfdb3a3ff2774839ce31cb0216fecd7c4b8445ecf277dbe747be5fca708e37d9d5b7ae193e933abbe627bfdb42fffec26ed8edefae435a8a728ef7f90344f74bcd93e0b1eed83d7b608fec89c5a7142f7cc45e58216dec8dbd7fcf3a968dd9075b613db6cad6589fadb30db6c9066cebcf891ba186db6c87ed7e973ede8716efb17d366407ec901d95cc3b62c7ec848dbfbf9dc538078c5b85756a9979f1949db17376c12aacca6aacce1aacc95aac8d3dcc3aac2b78415d1f8209f1d5760a2994881fa3b22909a03f564528a2efb7eb9275bc845a5d7d9bbe6b7123026aeb2ddb2e9397dd8a3bc875ff7d2360220539d7150fc5d70de2513c8967f1225ec59b78cfb4c6587c8895c2fc557cf52b6de47dd113ab622db63d1b8abe58171b621370dc1f03712bb644a9fef8bb44ec885d18037bdfa30d5a0d1e0e1907ff1d8a8392b90fc5911889e3ef6f6711cef1137152dcc389537126ce17b6e64254f84529aff9067e76e939908d8055d6f1ab2a6aa24e7fdd15bba2219aee9796687fbf6d7faf88e3f8ddd124dd3f29a2fb9c735c42245f981d12922fb4c4580a29cbf08df42aa9976d23eb01dbe287730c5b9966aeb432000f5095e1df319e7faf88ed645e35f20f891e503ee31c6ff1a0b84f9297f24a5ee76b9337f256de95671cc891bc970fcbb41078f5e818f70433d7dc6807af1bb191fcedfdf0ddc26ee54be2e5fe96a86c7959cc393e94af65f67fe51b6b2db08391cbb06d222bcbdcf3946388d89ce5e5c7efb6f6af12de972bb297706ec0367f778dd2b298737255ae9562c5a5bcc9d5752dfb72fd2b9c931b7209dbc901ac1a623fd7935be572421cb827b7d90afc7b67369a646371cd32dbcac672372b3a1475b927f7d9891ccadc689edd4e7b62b7dbb1c232fcf3276dde9287c9cc8a51c5dc3ea73c9223b92f8fe5893ccd8e95e5d974b962479ecb91881645d630675cc86db1270ef2ebbc8873fc943d9764c57df63ad58dbccad718e7e4bc7c5427abb2e6ec5e978dc279e2773db6645b76645771c5643b7e1bf084b330230f95943da5667382ad5795141b2a554f712c57d83af89d4b6560cd722bebac2fabc0a6995e018e6b65c5dda44fd909db8fdf9bab0271a34276286ec4502eec73141561049bf274eb6227e9090be3700b346b68dda53c64fbea4abea8ebf45e1cbb15fb71fb27bb7af240dd884b7129ebea16f2dd418dee451247c55ad583d8528fd0cac7b88d624b06f228abaef99ce36beaa9eccd38f59c670fd6562f5f665c5cc26bd9f955bda977dc2f009bd58b310ed61503e813258fc8dae398b7eac33389ddaa0fc7e3d6b446de572b714ad99ef815b6a57a2ade171ca855b5a642d557eb0cf44b037d325dd30757cffd894ea8b19d15b5f1b9d7735c4de581d1b1e97b46c6abd821c4783d3570f84c8cd456ec0be5fea4f7e4998adfea6b54b28b2477d5d64c4d8c4a78ac76d51efcadaff6d550c050743b02461dcadd79462ce0dc49c9793566c4911ae5f4fcf177300e4a3861399e344fc4b5b795926cc38ff6859cdb565b6c8d6d4fc63d1babd0f1e1d0e787ff43dfb93255d6b1706fe305cf483e91ddc0aa39de8f69b23db90bfd7d2ca4e8c98172f551a7e9fab85d58ab82893f5567338c1b00cb0f3ff773e258ad80b7f5dc7857e793b6c0ecb829362062d849a5be703b791b93541009c4ef290e5425f9cbdecc8efa4076448f746e41bd02b505ed72b76ee3530c5583911680179d8b68f238c7d7d51227abaaa19a399c6b7d0fe7f83b7b2e77df04c6e04612db04625df560a6fb9007f93d076bbe33369ed95519c57dc8f625ed3caa37377b19753ad5d7d2ed3c07ead2fb2255737f69415c789bae933c566de8b59a4aeddea84bc790a427e12fdd94af7a82197b471c17dba7041eddf99d1258af8fd3658b9dd9132de65a079e38890844843be6ea3eb140948a1007b2ad2ebc0d21b605bf1daf54d275837254fc57cd67fd721ee734d3621946c4ef70cdd4a7bf8b73724397bce304d17217e7d7a417b486394a9d2b5dc4ef39bb7ea855c87929c2a49766e224d74ad72becc0cf3930afb6630eea704edf2d4474e05be4636a2625cec9646763c239d0b9c146655a8d33753c67aa4f774ac02fb9b95806fe2f9e736212cf4d3807de1666ef8449f2231e57ec40cfec02aa6b7796b7ae676e0765734e5fa9527b2429ce5debccd59cbed577fafe7b58a71ff46319ebc7169463d188a3a814f302f5a8daaacb76646e143a119817db6e77b54a9c8168def5d2a148ed47ea27f7b7b63fc1d5cff17cc4fa5927e5a2eefa79a0925d47cf393648fee23937d02f6577ad259d7bc94355fd2c2d8c0d9c859373edc4cf25a365c239b6cfa6d60610bd815dd5e3dcda7e575d41fa35fd3afdf71ccebd2de7e51c2372e22d3dd61fdfc4baba5ec92e6391c07c361277102169dd9bf27a03f5c18eb3f73d527d12124f23af0df9045e29a98b3c93eeb449912e98df0ea1378289f7986185dbb5d5d6f7553ee7644b0d32eb752b4fd908d6bb07f38c943e9adb979fdc2881d655f064565df8bf2de05ca0a6635858a593f73b9f8947b6310294dd69eb66714e08bdfa052fb4a633bd06f4d23afff81e4fc7f8b2cfc3b231db95e72284a8792de5f56ec57e9e1f01e628b7d2437e26f307c4d4ebae076ac98a70e43c57e06f70c0ea25fe628b9417399a435c6ff8d9359773037195e9298ff506ac13bb6a5fdca88bd935b93c2ac23976cb56b4a55367abf9e79c936d39158f884351252b6ec80b3fe3c2083f712bdf58eba6b49f718e193df802e7b674ce2d0d71ae77f4ee77f83a75c2bf78bb491cc77b702a898a656f9a19ec16e6be11db84de5e8398cbafd80622898d44db7931abf790adb056a9b9be6bf99326f0ab2df8bd2773c6875c713db2efd3e7714e3ea95a66fe8bd48e88993d6b00d6e4722e6e9d6cb26d71a5f6a4914f5e8b1ea672e7f9b90d39b56e6293138f40056c15acba29427da0d6219a6bc66fd59f1d31599cd3856f19e5b0ee30ff5e893ed223bdf50d9eae9257427101cffb82379c9cdca5c6e88e7e912d7dac4fc0a247fa1456bef7e4e752f6d667183be36a4fc6ec8b531cf85585bcd03db7d61de5706ee47ab1ea63ec3cce29c932573afa5c3da66284997b77a29ecd39988fb754a498ded74fec44487624461077399faf8bccadabd35e2bfeb2169524217251ba129fdc282de3539c0b793ebf4337cf3958c35c7d910f5c2f885a754dd7bfe1199e974577098a8a1ca9a4cfd82a8e46986d76605608c44d7aa680b9d7602c9fb2f635f6b9eaeb4b1de993d8cba9f7c98e81041f12ff45e68c4058efc5b1f7aa5f85e4734e656a10db7a72a66ad58c9f93cfd99c038ec4df84db00be1dfbd6e90a9e0feac6e79c9b9d29216ac3f16844add8edd70cce3575f38b7eaeb5781dc8a46eeb8eee7e89d78aef7f03e78e2627e17a133927b761c61a405cdc4bb70263b3f4cacecda638b70562536de1fcab6e553216e496e18ea7399c536f6ee6ecf85dd3b29c63b76ad370dd03391677b3f19cd8c9e21c1bc43be4bac73ed2ad6363bc6b27138695e0dc05325f9d153d159ee79c597267ce4bfc1587cfcbe58ff1d70f96f777eac47cc39388f2791211a9fb987310e974dc989dd9519356adcd720e38b1929adb70ed96ba1d09bdbeea3c59ceb3ba300b175ab7e671ced9b11fdf0bc8d22f8ee73927daae4603636753e389c7329c13d7428ba935ef6732cb39dee7e62bef1f318199dbffccb1d6904b137d61967dfefa1becd847728638d06771cfb1ddd8b210a3cdec4d809fbb9de79cdca57b527e7e1eaaa93b7e6adbedfb66fa7d79e676afac9ea45e82730bda36c6182dcd393972b3bd9cbdd5c5fb6e0dbe14e7e814c24e4e2c3e9339ceb578895bc1738cbb345765ee908bb1b93637aac4cdf7945c167bc304782e60d0ec1e395a5a067e9700fae2107bc571e7607a6d065ab631e299e61cdbd29b69ce293b7d6a2f9b8ed330bbcedf8552bd988fb0c238f37f53fc7b39477b6efb93134f7612c712c0b9a99b4d60870bb4c3329c7311dd5a3c5fcfdfa080f5cad1fc1ed41ce79a7c7749bedd9a3b5398eb13310fe6d13c2d51deb37929a25f5ea83518eb2ff278f69c4b5dcb43daa35b633d64a53c703d05f1709a25d24a7ab6608673b7fad53fe7e2a43b5bba3a753bc7ab6a773a7e520ff1acaeded3e7adb8479ce61c5bfb929f73a344dc4c6ef3a96b7decc6c0c654ca91a2bdca09e7e401ae99529c3bc196ce730e4ac2fb2f57d31616c7ea5c1dce4629199c2bf5bc4d8a01afe64dbcce6a2f267c68decdd894dc2f5627acd01e9ddc71eb04889dd59a1c0809d1433f8e82e4875bbfe1aedb50500c0a63bee552afcb136403fc65177e0fb23817efb1a5f6c806ea6daef4f82eca40046625be2944658f55a402f8ab513c7d7f53a39fdb9adc24472f1a7ff97119ced1aa7a6de2e36175bde9d875cf06be75108f0dfd0e5d9a73eefe5530d93d917bc861b63abf3a055b5ee1bd1dffbc30b4f286eda9d82673f76c6739677a65673ab36ad64c5f7cf9d95bb36e364a965cf0d6b0dc5187607f3a75005b564507ef71ba31df1357e999571c2a17f9438a23118a7dd1d53d98212f63d6a977363353c058e6c4c7813ccc3a85176dd6539d3872971d5835dce93dd97627623dbd31bd57aa5c9d4cdaf3b9930a33504b3c7f04abdafd69d6b832aad4babae26cd36c0958b9ab00ace3da30d97b663726b6573f75eadfc3f3e19c33914371837716f48508d926db80083110f73ae3b6df1ce7b64b7bb81db3fb1defa316e766cfec9739a53085cfbfa4d5e7ba6156a66f80c99a5ad55c5e4cdb908de58a399071b435000fb3af847a90fb6c53bfaaa1d89d3f2f67bbe0c96ec1be1d1d66ef1680c6b138521fc919f95074d4307d33836ab925b6744fa64a602bfa584973b8cc9390bcaf76d499ba9b3d05117bb0b6de7723f05234d886da94db6c47f55485ed4d9e816563fd2a8dea4f6e3088ba8668505de53d9b0d6cde8058a59fb471dd1cb0edac387a8e73a5d69166648ecd37be51c49c9a3359d8db9952518e8ed8ae1c42bc5b633d71672e4c45699857324f59459d1dc17cb1ab2f6573c20cd090e9cde3930a3962bbf9ef5980f91956bef24429063dac7661759c71b2002c1900ef52bfc44f5d88de6cfc545480eb76fec6a4bb8fb9252379ae4f277703e66fd5c933f631fd1c36c4ba4750bfdcfb2d309b57630b8397db067b7ce4ddca9e8be76e0bf7b8fbfef272d6c817f11e7f85b8d8e918fba39edafc91a232e7e70adee7550dd3e69927cf5f97f8dbcb856af10da75f3ff2eb659673b6d09b6bccb365f6cbefadc917fc66e40fe7fe336519ceb1a7623b635f11de8fbffdb9b81e36e72ee48ffcd93217cf9d7dc6381b9abd5ff1ce36605d642f17d6a5f06d61f960aff82dab9823d3fb1575ffb5c299bde6b5e5da25c65cf0539e79d79fb7f8aabd92abf0ef9b72daf91adf875cb79a9997cf9f35e49f9c08d83b9bfbdcf432621feca37dcab3876ad9054f75b3827ece5eb137becdc7fc82d7d509bb624bae03131bf5d9a57d1127fc8371beb1a837789f1ff00adfe15b7cc06fd87b76df7e525a8baff01bbe91fd2b931081efc80db9214eb429f7764821ecab7d931b8c817ddab3ede02d7da84ef8b63a019b31fb6ec7459eb78bbf51a357a1c56f98d77ef0b9b78994db9f630f768927111689edd955bb66fb763dbbefec86ddccad4fa1a75298b4b3e326f3d982e2221ff895bf9ba0ea8b9e07b25be9f7cbcb3b5629cf3a60ed7b7c0f36e75735790ad986bcc08d9e743b6cd2db4cd999dd1b3eb4bb36c506e0d00dcf799234c9d367712dd2d60ee74f0be6fcdceaa29b1e76cf2cf56ea405bdb21feb15dc0eed813d9c7fca015a7e947bcfa5d0ee3cbb6433ab9172fb7a19751ed9c957cd764c233f25cce45363586ef0d2bbbbbce1f2be668fc9f49d6ebb5dee7973de4de73573fbfa30eff6a6de1f3d56f545be8ef7e5ead4ddcb23796f33fcc21ce71e6ceed9973db567d9a58931ac34cfed85adf07b5beafb49b6365542dd366cd3b6d2b337442bedacb79181df1e15b2ac044f3f9df78b6fb2348d94c6ba5d70bb85dff39979833198494acd80d631438bec7bd1363d1edf16d525a31dbdd468580ff87c0a3e34db33e7ef9736e7a96e21f853fae625f8c5679df99eda32f74a82b991c08741fc289d0a7460021b042e5558e6992cae66dffd1f44c1657095be2f105c0737f3b561aad84cf237736ea1b79de71cb4ef16e2ba32a3f297700e4670e60d0d21340bd2e70447fc32eb5df67c2db84bbf5910fe7f2fcf2716bd3f17dc070f694b058fc153f01cbce866f01a4c7d3f3328e5df837190719f2458097ac1ea84bbc15ad09f4bf5526c2d30cfb960bd4c0d33fa6a9a73770bcacee01c44120f65be7bf17b3917cf98a60731da24e23a02549d7eab387f0c36588a05f22ed8c8f671b1cc716ea89eb222ba603348226f711e6c05dbc1acf7f0294bbdd3d19e077bd97af851b01f10eb583b38982be7b0d8cd8279cea99c7572e1befa22e7400641e137e7ff6ece39fb5f06a3342becb6e5b6aa1f99b1d7102fbf839f4a73e6753e364ccbfcf3107ac566799ee3803caa780d4e83b31c9ec4294b45e8763dc87f73ec765009dc2d0b98c36bd3bfa993a0e059ef1fc9b971d028fafe8b3f8173d012c1f88c2ffae087fc1a56154fd3b7328226bf5ffc6d8579ce0547f3cf7d05ad80d65b4127e8e6d8d149c8c352f79a6c2b5cf0c44fd00fa5957c28de4335f3dbc7a2f5e294b5e6e3b92fbee9f41b38076b0fbec20ac5a37f06e7c0173d86faf3bb95f63d6f8d3191ace75bc18fce6832afa189ef7c84360c16971986e6747189d3c23a61f489c6cbf02abc0e2ad37f2dfe46b079ce850bdf4d52a0afbec039c6ecb6f717b2d0fb1bff14cec5519bfdeceec5887ffa3e9eece7f883b93357a01acc47e16d78177e72a752be973bfb5723f1e9b310e143f818cea49285efc1cf73ce2c78cf76a1be5a8a738cf1bd50d98e7eb383f0395ead6b018cf974dfe4cfe11c30e0852f78ab08ac227491157916e7c217f636ad4d0fc2d7f0edf3b7ec87efe1b8dcc998be0a97786f0ef4d8273be2a97e9fe3dc57df3bb104e7e21d8607cf2fdee78f9ab1677ec4de6cc6bb4fa7e54fe21c94d7c9ff726fd028b6f398fd5e263e77a3235c097b79654dc4dc8625bf9214be84a5df200b7258fc0b60f39c2bee2373faaa3ce75ee7f7afe54308ac8399f6932ffce03bb2fe14ce9917f190db2b392706b392fdfeb9b0bfdc9743c2f530e72c3a4fc2cdb0fc3ba0ea65deb4f927f8b9702b6b9f9c37e3b52044dd9d85f704aeff24cef1fdd9397022baa0bfc9e61c6f85dbcb3c611fee8425bfb81274c2bcfdb95c51f5624f53535be6e3b92f9eb796e75c5e7f86fb3073d6e3b82ecf6ff3167e4ff2cfe01c5f0b87f9fd62df8bac20f2df271c1ed8d24f8001e70e83927b5fe15138b74a5e2c729d3f95393bcaf0735fbceb599e7322777dca1fb975377e0cbb9c6f151f0677b85bfa67702e3c5ef8cde88b6054e46c28f7bde94ce7cfdbf99c3b297b63ddf4e4e27b99f3320a4bedc6cc73aee81c905be7f273eb82ef5886fbea09c6515d3cc84dbe9e9e83799f091f3dfd7ecef1357ec76677496765ccae3ebfad95ff7d083b2a1fd3856765e7d6b0d4978841b617f55fa6ade6f7e7967c2f6cd257dfca39777bc3d0d9cf8e0dcc3670a1ca845c65c1c4abe4722e7523439d94b30d4fbfc1f78d2f9ca138e3b7b3df318aef7aeac1dc3ef1213f593c0f2df826c93ac41aa5beb20ab6bdb02563a5b052b2846ad9e7b733fc5ccefdc7a2f2dd9cc31bbbc92d3f58cb8a133d989ec5f238a759ea76e1912d77d69de2abfdb00bbe8fcd0c3f9be2d618a2cc4d7e17c67734c73c98faed883d2f8eeb167defcbbcf04fce08e618510b4b3df10a3169a38c7e58e3158a52a7ca98df2b515f7b26e2fb39e7ee47dee5df5ccce71c13e91ba9e6bcccdd3c963e53dacaff925a781a1cf2a95b23f2958b4949ccd8abb0995e734244a0f26fb42dfeaea16165e7d7b01596b8091b764a697f2bb77aa07e9f3f6fbdd0acf8fe5e8655fe06ceb9d4ab41ee13ed799ce3359eba7f284e6ce1e72f999dbab39fbbe369b7a66fb7d97793f1f608f04f53a998022f9ac3ff4fbedfbac64bf921b06e37cab86f9a2d621ce5ee6967890d8a9d8acfb4619e73601156297e923167dfbf8b737dfd36f334c1e79ceb9b617a66933977d8e7f2315649e53bcafbe2863d0e46e9084b37d97bb607d38f7cea3dd47a6007d975f9ec3bd5e129f0b744546756a3c21e247c658f85351f4572b9e7b5b238075287f8f78137ec182276696f7813668b8e7c900feeb9bd5a780af2a24659d1e3dfc539772a761234b37646f338e776f00ed3e9ccd1e76ff716e380a7ee911ff1ebac1b96bc6f47d373265372c1896aa4c2ad74146ab7f959d64d8ccf38e7faac545417e9a8d0298195d127cf4ca7256c16bdbb9451ff9cdba51351275ad813986bced913447b03be1b49fec22fd995ed9aedd9fee0fb537b06dfc8b95860963a9c1fe5f99c8b9fa549df3e931b10a72df0e1c0a41b7e96e2c611bbcebe6d2e57cdf4939ee7a697afd7e5a9b169aebcd9ee3ceb3ee79c7b66a1c417e2f47d144405de291c4551e19d39bb1df6978dc082a3e84bdf1e8015ddcc7cc537d2678e59d14d927209cec16cf9c2c3595fb79073b07ae4e93da77124cd30fbab2d91e2c77c30f50cca207337ba2f37a777e3c403f8f74f7799ec7534fd6c433dd4b34fb816e15cbc7b981fdd664974b3f8dc35ba8deea2c26f9a63dab0e5579a10932ef9b65a928b607ddad630fb267d0633d482f7d9f22ac54c25df93c90c0fa677c3d81b5ff81407b3d1034bbf87fe024a8e421dd4ed2d8f9fc4bf0a38a0a6dc48f9d023f06367595fdc95d7fc606aafe68247b6e097e52132799eaafb45743d7d13bf18e7f850b3725f8d881ea3a7bc91295ea3e7a8f857abb7cc66b9a7f3e66abf0aac5be26bb4d8d74163f6194d88baeed0f303e336e79f539f48b81ffb58b99ef725e5051c326668d3a7e99fee29f235fdc69fed7bc1e87b3b68b2c08eb2c6321fdaf1f4335ce170f689eb45a2afa2d7e978864d4527c538e7f6ca1b6566d8f09dbd446fd1bb789bfab2c7bb10d138fa085e8beab1dbb6f3d5f7c64204b365ab86c94d534ac263be2a7598f13e20beceabf636ecf36afed34d287295efe59fb62eac35946186fa903d435c1965455c19791ecd8bd9e62b6193c5b3b397d892099277918428b507aba69c91cc87d1ab3d71efdab8805115f2d5725f698ef90ff3f01ecccd17b180d79b8ab58a722e167bacea65fd45b462a2a8171eb0f768355a8bfad17a89dc173016ffc6378efd270b5f679786d95d63a20dbe19de449bbc0dab21f6f9d30a130de129acdbbf744e0891a6fcfc7d258bc5de440f4b7e4564995cd7fc9bdf54f1237f8294e39c8b5036f4e01bbe11f789d86df5b42852fa917f5f29cb391741efc31c5ff2f4bf94d4f925c44a5fbcfdf1237faa94e75c2cbcc3cfcc8237c37d49b658a5e8bafc47fe1d6539cec52b13580b76d9dbb7fa3b58254503bbf3b59d911ff9d36559cec5c2877c9f0576b9f5c19c30151c16d9e9fe917f77f90ae762e16b5273b3e8e65711d14df5644bdfc6fc917f4ff92ae762017ff7681ad1161fc9b552fb77752d7845bdea37fef895fb6c3ff2ef25dfc1392fbc2557f9b17ae5bb9feca61c411c78ae0ff96d78a01ffff3de63fe238be53b3987c21f799357d93b6faba7709b1f46923dd9f87db803550fb76d378afd5ad7ee943f83fc91ff0cf97ecefdc88f2c961fcefdc8af961fcefdc8af967ffedffff98fff0759629c80</data> + </image> +</images> +<connections> + <connection> + <sender>buttonOk</sender> + <signal>clicked()</signal> + <receiver>ConfigurationPanel</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>buttonApplySkin</sender> + <signal>clicked()</signal> + <receiver>ConfigurationPanel</receiver> + <slot>applySkinSlot()</slot> + </connection> + <connection> + <sender>Menu</sender> + <signal>clicked(QListBoxItem*)</signal> + <receiver>ConfigurationPanel</receiver> + <slot>changeTabSlot()</slot> + </connection> + <connection> + <sender>DriverChoice</sender> + <signal>clicked(int)</signal> + <receiver>ConfigurationPanel</receiver> + <slot>driverSlot(int)</slot> + </connection> + <connection> + <sender>buttonCancel</sender> + <signal>clicked()</signal> + <receiver>ConfigurationPanel</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>buttonOk</sender> + <signal>clicked()</signal> + <receiver>ConfigurationPanel</receiver> + <slot>saveSlot()</slot> + </connection> + <connection> + <sender>Menu</sender> + <signal>clicked(QListBoxItem*)</signal> + <receiver>Tab_Signalisations</receiver> + <slot>setFocus()</slot> + </connection> + <connection> + <sender>stunButtonGroup</sender> + <signal>clicked(int)</signal> + <receiver>ConfigurationPanel</receiver> + <slot>useStunSlot(int)</slot> + </connection> +</connections> +<tabstops> + <tabstop>fullName</tabstop> + <tabstop>userPart</tabstop> + <tabstop>hostPart</tabstop> + <tabstop>username</tabstop> + <tabstop>password</tabstop> + <tabstop>sipproxy</tabstop> + <tabstop>autoregister</tabstop> + <tabstop>Register</tabstop> + <tabstop>buttonOk</tabstop> + <tabstop>buttonCancel</tabstop> + <tabstop>Tab_Signalisations</tabstop> + <tabstop>SkinChoice</tabstop> + <tabstop>useStunYes</tabstop> + <tabstop>STUNserver</tabstop> + <tabstop>playTones</tabstop> + <tabstop>pulseLength</tabstop> + <tabstop>sendDTMFas</tabstop> + <tabstop>Menu</tabstop> + <tabstop>Tab_Audio</tabstop> + <tabstop>codec1</tabstop> + <tabstop>codec2</tabstop> + <tabstop>codec3</tabstop> + <tabstop>Tab_Preferences</tabstop> + <tabstop>Tab_About</tabstop> + <tabstop>useStunNo</tabstop> + <tabstop>buttonApplySkin</tabstop> +</tabstops> +<includes> + <include location="local" impldecl="in implementation">ConfigurationPanel.ui.h</include> +</includes> +<signals> + <signal>needRegister()</signal> +</signals> +<slots> + <slot>generate()</slot> + <slot>saveSlot()</slot> + <slot>changeTabSlot()</slot> + <slot>useStunSlot( int id )</slot> + <slot>applySkinSlot()</slot> + <slot>driverSlot( int id )</slot> + <slot>updateRingtones()</slot> + <slot>updateAudioDevices()</slot> + <slot>updateCodecs()</slot> + <slot>updateSkins()</slot> +</slots> +<functions> + <function access="private" specifier="non virtual">init()</function> +</functions> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/src/gui/qt/ConfigurationPanel.ui.h b/src/gui/qt/ConfigurationPanel.ui.h new file mode 100644 index 0000000000..4261c87672 --- /dev/null +++ b/src/gui/qt/ConfigurationPanel.ui.h @@ -0,0 +1,389 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you want to add, delete, or rename functions or slots, use +** Qt Designer to update this file, preserving your code. +** +** You should not define a constructor or destructor in this file. +** Instead, write your code in functions called init() and destroy(). +** These will automatically be called by the form's constructor and +** destructor. +*****************************************************************************/ +#include <qdir.h> +#include <qmessagebox.h> +#include <qstringlist.h> + +#include "globals.h" +#include "ConfigurationManager.hpp" +#include "DebugOutput.hpp" +#include "QjListBoxPixmap.hpp" +#include "SkinManager.hpp" +#include "TransparentWidget.hpp" + +#define SIGNALISATIONS_IMAGE "signalisations.png" +#define AUDIO_IMAGE "audio.png" +#define PREFERENCES_IMAGE "preferences.png" +#define ABOUT_IMAGE "about.png" + + +void ConfigurationPanel::init() +{ + DebugOutput::instance() << "ConfigurationPanel::init()\n"; + Tab_Signalisations->show(); + Tab_Audio->hide(); + Tab_Preferences->hide(); + Tab_About->hide(); + + /* + // For reading settings at application startup + // List skin choice from "skins" directory + QDir dir(Skin::getPath(QString(SKINDIR))); + if ( !dir.exists() ) { + _debug("\nCannot find 'skins' directory\n"); + return; + } else { + dir.setFilter( QDir::Dirs | QDir::NoSymLinks); + dir.setSorting( QDir::Name ); + + QStringList list; + list = dir.entryList(); + for (unsigned int i = 0; i < dir.count(); i++) { + if (list[i] != "." && list[i] != ".." && list[i] != "CVS") { + SkinChoice->insertItem(list[i]); + } + } + } + */ + + // For preferences tab + + /* + SkinChoice->setCurrentText(QString(manager.getConfigString(PREFERENCES, SKIN_CHOICE))); + confirmationToQuit->setChecked(manager.getConfigInt(PREFERENCES, CONFIRM_QUIT)); + zoneToneChoice->setCurrentText(QString(manager.getConfigString( + PREFERENCES, ZONE_TONE))); + checkedTray->setChecked(manager.getConfigInt( + PREFERENCES, CHECKED_TRAY)); + voicemailNumber->setText(QString(manager.getConfigString( + PREFERENCES, VOICEMAIL_NUM))); + */ + // Init tab view order + + // Set items for QListBox + + new QjListBoxPixmap (QjListBoxPixmap::Above, + TransparentWidget::retreive(SIGNALISATIONS_IMAGE), + "Signalisation", + Menu); + new QjListBoxPixmap (QjListBoxPixmap::Above, + TransparentWidget::retreive(AUDIO_IMAGE), + "Audio", Menu ); + new QjListBoxPixmap (QjListBoxPixmap::Above, + TransparentWidget::retreive(PREFERENCES_IMAGE), + "Preferences", + Menu); + new QjListBoxPixmap (QjListBoxPixmap::Above, + TransparentWidget::retreive(ABOUT_IMAGE), + "About", + Menu); + + QObject::connect(Register, SIGNAL(clicked()), + this, SIGNAL(needRegister())); +} + +void +ConfigurationPanel::generate() +{ + // For audio tab + codec1->setCurrentText(ConfigurationManager::instance() + .get(AUDIO_SECTION, AUDIO_CODEC1)); + codec2->setCurrentText(ConfigurationManager::instance() + .get(AUDIO_SECTION, AUDIO_CODEC2)); + codec3->setCurrentText(ConfigurationManager::instance() + .get(AUDIO_SECTION, AUDIO_CODEC3)); + + + ringsChoice->setCurrentText(ConfigurationManager::instance() + .get(AUDIO_SECTION, + AUDIO_RINGTONE)); + + // For signalisations tab + fullName->setText(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_FULL_NAME)); + userPart->setText(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_USER_PART)); + username->setText(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_AUTH_USER_NAME)); + password->setText(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_PASSWORD)); + hostPart->setText(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_HOST_PART)); + sipproxy->setText(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_PROXY)); + autoregister->setChecked(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_AUTO_REGISTER).toUInt()); + playTones->setChecked(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_PLAY_TONES).toUInt()); + pulseLength->setValue(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_PULSE_LENGTH).toUInt()); + sendDTMFas->setCurrentItem(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_SEND_DTMF_AS).toUInt()); + STUNserver->setText(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_STUN_SERVER)); + ((QRadioButton*)stunButtonGroup->find(ConfigurationManager::instance() + .get(SIGNALISATION_SECTION, + SIGNALISATION_USE_STUN).toUInt()))->setChecked(true); + QRadioButton* device = + static_cast< QRadioButton * >(DriverChoice->find(ConfigurationManager::instance() + .get(AUDIO_SECTION, + AUDIO_DEFAULT_DEVICE).toUInt())); + if(device) { + device->setChecked(true); + } + + //preference tab + updateSkins(); +} + +// For saving settings at application 'save' +void ConfigurationPanel::saveSlot() +{ + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_FULL_NAME, + fullName->text()); + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_USER_PART, + userPart->text()); + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_AUTH_USER_NAME, + username->text()); + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_PASSWORD, + password->text()); + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_HOST_PART, + hostPart->text()); + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_PROXY, + sipproxy->text()); + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_AUTO_REGISTER, + QString::number(autoregister->isChecked())); + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_PULSE_LENGTH, + QString::number(pulseLength->value())); + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_PLAY_TONES, + QString::number(playTones->isChecked())); + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_SEND_DTMF_AS, + QString::number(sendDTMFas->currentItem())); + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_STUN_SERVER, + STUNserver->text()); + + if (codec1->currentText() != NULL) { + ConfigurationManager::instance().set(AUDIO_SECTION, + AUDIO_CODEC1, + codec1->currentText()); + } + if (codec2->currentText() != NULL) { + ConfigurationManager::instance().set(AUDIO_SECTION, + AUDIO_CODEC2, + codec2->currentText()); + } + if (codec3->currentText() != NULL) { + ConfigurationManager::instance().set(AUDIO_SECTION, + AUDIO_CODEC3, + codec3->currentText()); + } + + if (ringsChoice->currentText() != NULL) { + ConfigurationManager::instance().set(AUDIO_SECTION, + AUDIO_RINGTONE, + ringsChoice->currentText()); + } + + SkinManager::instance().load(SkinChoice->currentText()); + SkinManager::instance().save(); + +#if 0 + QMessageBox::information(this, "Save settings", + "You must restart SFLPhone", + QMessageBox::Yes); +#endif + + ConfigurationManager::instance().save(); +} + +// Handle tab view according to current item of listbox +void ConfigurationPanel::changeTabSlot() +{ + switch (Menu->currentItem()) { + case 0: + TitleTab->setText("Setup signalisation"); + Tab_Signalisations->show(); + Tab_Audio->hide(); + Tab_Preferences->hide(); + Tab_About->hide(); + break; + case 1: + TitleTab->setText("Setup audio"); + Tab_Signalisations->hide(); + Tab_Audio->show(); + Tab_Preferences->hide(); + Tab_About->hide(); + break; + case 2: + updateSkins(); + TitleTab->setText("Setup preferences"); + Tab_Signalisations->hide(); + Tab_Audio->hide(); + Tab_Preferences->show(); + Tab_About->hide(); + break; + case 3: + TitleTab->setText("About"); + Tab_Signalisations->hide(); + Tab_Audio->hide(); + Tab_Preferences->hide(); + Tab_About->show(); + break; + } +} + + +void ConfigurationPanel::useStunSlot(int id) +{ + ConfigurationManager::instance().set(SIGNALISATION_SECTION, + SIGNALISATION_USE_STUN, + QString::number(id)); +} + + +void ConfigurationPanel::applySkinSlot() +{ + SkinManager::instance().load(SkinChoice->currentText()); +} + + +void ConfigurationPanel::driverSlot(int id) +{ + ConfigurationManager::instance().set(AUDIO_SECTION, + AUDIO_DEFAULT_DEVICE, + QString::number(id)); +} + +void ConfigurationPanel::updateSkins() +{ + SkinChoice->clear(); + SkinChoice->insertStringList(SkinManager::instance().getSkins()); + SkinChoice->setCurrentText(SkinManager::instance().getCurrentSkin()); +} + +void ConfigurationPanel::updateRingtones() +{ + std::list< Ringtone > rings = ConfigurationManager::instance().getRingtones(); + std::list< Ringtone >::iterator pos; + + ringsChoice->clear(); + + for (pos = rings.begin(); pos != rings.end(); pos++) { + ringsChoice->insertItem(pos->filename); + } +} + +void ConfigurationPanel::updateCodecs() +{ + std::list< Codec > codecs = ConfigurationManager::instance().getCodecs(); + std::list< Codec >::iterator pos; + + codec1->clear(); + codec2->clear(); + codec3->clear(); + + for (pos = codecs.begin(); pos != codecs.end(); pos++) { + codec1->insertItem(pos->codecName); + codec2->insertItem(pos->codecName); + codec3->insertItem(pos->codecName); + } +} + + + +void ConfigurationPanel::updateAudioDevices() +{ + static std::list< QRadioButton * > buttons; + + while(buttons.begin() != buttons.end()) { + DriverChoice->remove(*buttons.begin()); + buttons.pop_front(); + } + + int top = 0; + std::list< AudioDevice > audio = ConfigurationManager::instance().getAudioDevices(); + std::list< AudioDevice >::iterator pos; + + for (pos = audio.begin(); pos != audio.end(); pos++) { + QString hostApiName = pos->hostApiName; + QString deviceName = pos->deviceName; + + QString name = hostApiName + + QObject::tr(" (device #%1)").arg(pos->index); + + // New radio button with found device name + QRadioButton* device = new QRadioButton(DriverChoice); + buttons.push_back(device); + DriverChoice->insert(device, pos->index.toUInt()); + device->setGeometry( QRect( 10, 30 + top, 390, 21 ) ); + // Set label of radio button + //device->setText(deviceName); + // Add tooltip for each one + QString text = deviceName + " " + name; + + if(text.length() > 50) { + device->setText(text.left(50) + "..."); + } + else { + device->setText(text); + } + + QToolTip::add(device, text); + + + top += 30; + } + // Set position of the button group, with appropriate length + DriverChoice->setGeometry( QRect( 10, 10, 410, top + 30 ) ); +} diff --git a/src/gui/qt/ConfigurationPanelImpl.cpp b/src/gui/qt/ConfigurationPanelImpl.cpp new file mode 100644 index 0000000000..06dfc4c006 --- /dev/null +++ b/src/gui/qt/ConfigurationPanelImpl.cpp @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qbutton.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qsizepolicy.h> + +#include "ConfigurationPanelImpl.hpp" + +ConfigurationPanelImpl::ConfigurationPanelImpl(QWidget *parent) + : QDialog(parent) +{ + mLayout = new QVBoxLayout(this); + +} + +void +ConfigurationPanelImpl::add(const ConfigEntry &entry) +{ + mEntries[entry.section].push_back(entry); +} + +void +ConfigurationPanelImpl::generate() +{ + std::map< QString, std::list< ConfigEntry > >::iterator pos = mEntries.begin(); + while(pos != mEntries.end()) { + QVBoxLayout *l = new QVBoxLayout(this); + + std::list< ConfigEntry > entries = pos->second; + std::list< ConfigEntry >::iterator entrypos = entries.begin(); + while(entrypos != entries.end()) { + QHBox *hbox = new QHBox(this); + mLayout->addWidget(hbox); + + QLabel *label = new QLabel(hbox); + label->setText((*entrypos).name); + QLineEdit *edit = new QLineEdit(hbox); + edit->setText((*entrypos).value); + + entrypos++; + } + + pos++; + } + + QButton *ok = new QButton(this); + ok->setText(QObject::tr("Ok")); + mLayout->addWidget(ok); + + show(); +} diff --git a/src/gui/qt/ConfigurationPanelImpl.hpp b/src/gui/qt/ConfigurationPanelImpl.hpp new file mode 100644 index 0000000000..b8aeeddafb --- /dev/null +++ b/src/gui/qt/ConfigurationPanelImpl.hpp @@ -0,0 +1,69 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __CONFIGURATION_PANEL_IMPL_HPP__ +#define __CONFIGURATION_PANEL_IMPL_HPP__ + +#include <list> +#include <map> +#include <qlayout.h> +#include <qdialog.h> + +struct ConfigEntry +{ +public: + ConfigEntry(QString s, + QString n, + QString t, + QString d, + QString v) + { + section = s; + name = n; + type = t; + def = d; + value = v; + } + + QString section; + QString name; + QString type; + QString def; + QString value; +}; + +class ConfigurationPanelImpl : public QDialog +{ + Q_OBJECT + +public: + ConfigurationPanelImpl(QWidget *parent = NULL); + +public slots: + void add(const ConfigEntry &entry); + void generate(); + +private: + std::map< QString, std::list< ConfigEntry > > mEntries; + QVBoxLayout *mLayout; +}; + + +#endif diff --git a/src/gui/qt/DebugOutput.hpp b/src/gui/qt/DebugOutput.hpp new file mode 100644 index 0000000000..0001320532 --- /dev/null +++ b/src/gui/qt/DebugOutput.hpp @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author : Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __DEBUGOUTPUT_HPP__ +#define __DEBUGOUTPUT_HPP__ + +#include "utilspp/Singleton.hpp" +#include "DebugOutputImpl.hpp" + +typedef utilspp::SingletonHolder< DebugOutputImpl > DebugOutput; + +#endif + diff --git a/src/gui/qt/DebugOutputImpl.cpp b/src/gui/qt/DebugOutputImpl.cpp new file mode 100644 index 0000000000..20348d9036 --- /dev/null +++ b/src/gui/qt/DebugOutputImpl.cpp @@ -0,0 +1,32 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "globals.h" +#include <qfile.h> +#include "DebugOutputImpl.hpp" + +DebugOutputImpl::DebugOutputImpl() +#ifdef DEBUG + : QTextStream(stdout, IO_WriteOnly) +#else + : QTextStream(&mOutputString, IO_WriteOnly) +#endif +{} diff --git a/src/gui/qt/DebugOutputImpl.hpp b/src/gui/qt/DebugOutputImpl.hpp new file mode 100644 index 0000000000..0541aa319a --- /dev/null +++ b/src/gui/qt/DebugOutputImpl.hpp @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __DEBUGOUTPUTIMPL_HPP__ +#define __DEBUGOUTPUTIMPL_HPP__ + +#include <qtextstream.h> + +class DebugOutputImpl : public QTextStream +{ +public: + DebugOutputImpl(); + +private: +#ifdef DEBUG + QString mOutputString; +#endif +}; + +#endif diff --git a/src/gui/qt/Event.cpp b/src/gui/qt/Event.cpp new file mode 100644 index 0000000000..67f0964704 --- /dev/null +++ b/src/gui/qt/Event.cpp @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qobject.h> + +#include "globals.h" + +#include "Call.hpp" +#include "DebugOutput.hpp" +#include "Event.hpp" + +Event::Event(const QString &code, + const std::list< QString > &args) + : mCode(code) + , mUnusedArgs(args) + , mArgs(args) +{} + + +void +Event::execute() +{ + DebugOutput::instance() << QObject::tr("Event: Received: %1\n").arg(toString()); +} + +QString +Event::toString() +{ + QString output(mCode); + for(std::list< QString >::iterator pos = mArgs.begin(); + pos != mArgs.end(); + pos++) { + output += " "; + output += *pos; + } + + return output; +} + +CallRelatedEvent::CallRelatedEvent(const QString &code, + const std::list< QString > &args) + : Event(code, args) +{ + std::list< QString > l(getUnusedArgs()); + if(l.size() != 0) { + mCallId = *l.begin(); + l.pop_front(); + setUnusedArgs(l); + } +} + +QString +CallRelatedEvent::getCallId() +{ + return mCallId; +} diff --git a/src/gui/qt/Event.hpp b/src/gui/qt/Event.hpp new file mode 100644 index 0000000000..1fea8a1762 --- /dev/null +++ b/src/gui/qt/Event.hpp @@ -0,0 +1,63 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __EVENT_HPP__ +#define __EVENT_HPP__ + +#include <list> +#include <qstring.h> + +class Event +{ +public: + Event(const QString &code, + const std::list< QString > &args); + virtual ~Event(){} + + virtual void execute(); + + virtual QString toString(); + + std::list< QString > getUnusedArgs() + {return mUnusedArgs;} + + void setUnusedArgs(const std::list< QString > &args) + {mUnusedArgs = args;} + +private: + QString mCode; + std::list< QString > mUnusedArgs; + std::list< QString > mArgs; +}; + +class CallRelatedEvent : public Event +{ +public: + CallRelatedEvent(const QString &code, + const std::list< QString > &args); + + QString getCallId(); + +private: + QString mCallId; +}; + + +#endif diff --git a/src/gui/qt/EventFactory.hpp b/src/gui/qt/EventFactory.hpp new file mode 100644 index 0000000000..1a21f15688 --- /dev/null +++ b/src/gui/qt/EventFactory.hpp @@ -0,0 +1,98 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __EVENTFACTORY_HPP__ +#define __EVENTFACTORY_HPP__ + +#include <list> +#include <map> +#include <qstring.h> + +#include "Event.hpp" + +/** + * This is the base class that we will use to + * create an object from the "create" function. + */ +template< typename Base > +class EventCreatorBase +{ + public: + virtual ~EventCreatorBase(){} + virtual Base *create(const QString &code, + const std::list< QString > &args) = 0; + + virtual EventCreatorBase *clone() = 0; +}; + +/** + * This is the actual class that will create + * the request. It will return a Request + */ +template< typename Base, typename Actual > + class EventCreator : public EventCreatorBase< Base > +{ + public: + virtual Actual *create(const QString &code, + const std::list< QString > &args); + + virtual EventCreatorBase< Base > *clone(); +}; + + +/** + * This class is used to create object related to + * a string. However, thoses objects will be created + * with the default constructor. + */ +template< typename Base > +class EventFactoryImpl +{ +public: + EventFactoryImpl(); + + /** + * Ask for a new object linked to the string. + */ + Base *create(const QString &code, + const std::list< QString > &args); + + /** + * Register the string to return a Actual type. + */ + template< typename Actual > + void registerEvent(const QString &code); + + template< typename Actual > + void registerDefaultEvent(); + + private: + std::map< QString, EventCreatorBase< Base > * > mEventCreators; + EventCreatorBase< Base > *mDefaultCreator; +}; + +#include "EventFactory.inl" + +#include "utilspp/Singleton.hpp" + +typedef utilspp::SingletonHolder< EventFactoryImpl< Event > > EventFactory; + + +#endif diff --git a/src/gui/qt/EventFactory.inl b/src/gui/qt/EventFactory.inl new file mode 100644 index 0000000000..369d47e217 --- /dev/null +++ b/src/gui/qt/EventFactory.inl @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef __EVENTFACTORY_INL__ +#define __EVENTFACTORY_INL__ + +#include <qobject.h> +#include <stdexcept> + +#include "DebugOutput.hpp" + +template< typename Base, typename Actual > +Actual * +EventCreator< Base, Actual >::create(const QString &code, + const std::list< QString > &args) +{ + return new Actual(code, args); +} + +template< typename Base, typename Actual > +EventCreatorBase< Base > * +EventCreator< Base, Actual >::clone() +{ + return new EventCreator< Base, Actual >(); +} + +template< typename Base > +EventFactoryImpl< Base >::EventFactoryImpl() + : mDefaultCreator(NULL) +{} + +template< typename Base > +Base * +EventFactoryImpl< Base >::create(const QString &code, + const std::list< QString > &args) +{ + typename std::map< QString, EventCreatorBase< Base > * >::iterator pos = mEventCreators.find(code); + if(pos == mEventCreators.end()) { + if(mDefaultCreator) { + return mDefaultCreator->create(code, args); + } + else{ + DebugOutput::instance() << QObject::tr("The code %1 has no creator registered.\n" + "and there's no default creator").arg(code); + } + } + + return pos->second->create(code, args); +} + +template< typename Base > +template< typename Actual > +void +EventFactoryImpl< Base >::registerEvent(const QString &code) +{ + if(mEventCreators.find(code) != mEventCreators.end()) { + delete mEventCreators[code]; + } + + mEventCreators[code] = new EventCreator< Base, Actual >(); +} + +template< typename Base > +template< typename Actual > +void +EventFactoryImpl< Base >::registerDefaultEvent() +{ + if(mDefaultCreator) { + delete mDefaultCreator; + } + + mDefaultCreator = new EventCreator< Base, Actual >(); +} + + +#endif + diff --git a/src/gui/qt/Factory.hpp b/src/gui/qt/Factory.hpp new file mode 100644 index 0000000000..a89cf9212f --- /dev/null +++ b/src/gui/qt/Factory.hpp @@ -0,0 +1,58 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __FACTORY_HPP__ +#define __FACTORY_HPP__ + +template< typename T > +struct Creator +{ + virtual ~Creator(){} + + virtual T *create() = 0; +}; + +template< typename T > +class Factory +{ +public: + Factory(); + ~Factory(); + + /** + * This function will set the creator. The + * Factory owns the creator instance. + */ + void setCreator(Creator< T > *creator); + + /** + * It ask the creator to create a SessionIO. + * If there's no creator set, it will throw + * a std::logic_error. + */ + T *create(); + +private: + Creator< T > *mCreator; +}; + +#include "Factory.inl" + +#endif diff --git a/src/gui/qt/Factory.inl b/src/gui/qt/Factory.inl new file mode 100644 index 0000000000..5b96b6474b --- /dev/null +++ b/src/gui/qt/Factory.inl @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdexcept> + +template< typename T > +Factory< T >::Factory() + : mCreator(0) +{} + +template< typename T > +Factory< T >::~Factory() +{ + delete mCreator; +} + +template< typename T > +void +Factory< T >::setCreator(Creator< T > *creator) +{ + mCreator = creator; +} + +template< typename T > +T * +Factory< T >::create() +{ + if(!mCreator) { + throw std::logic_error("Trying to create without a creator."); + } + else { + return mCreator->create(); + } +} + diff --git a/src/gui/qt/JPushButton.cpp b/src/gui/qt/JPushButton.cpp new file mode 100644 index 0000000000..6e64b26290 --- /dev/null +++ b/src/gui/qt/JPushButton.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jerome Oufella (jerome.oufella@savoirfairelinux.com) + * + * Portions (c) Jean-Philippe Barrette-LaPierre + * (jean-philippe.barrette-lapierre@savoirfairelinux.com) + * Portions (c) Valentin Heinitz + * + * This 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, + * or (at your option) any later version. + * + * This 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. + * + * You should have received a copy of the GNU General Public + * License along with dpkg; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qbitmap.h> +#include <qevent.h> +#include <qimage.h> +#include <qevent.h> + +#include "globals.h" + +#include "DebugOutput.hpp" +#include "JPushButton.hpp" +#include "TransparentWidget.hpp" + +JPushButton::JPushButton(const QString &released, + const QString &pressed, + QWidget* parent) + : QLabel(parent) + , mIsPressed(false) + , mIsToggling(false) +{ + mImages[0] = transparize(released); + mImages[1] = transparize(pressed); + release(); +} + +JPushButton::~JPushButton() +{} + +void +JPushButton::setToggle(bool toggle) +{ + mIsToggling = toggle; +} + +QPixmap +JPushButton::transparize(const QString &image) +{ + return TransparentWidget::transparize(image); +} + +void +JPushButton::release() +{ + mIsPressed = false; + releaseImage(); +} + +void +JPushButton::press() +{ + mIsPressed = true; + pressImage(); +} + +void +JPushButton::releaseImage() +{ + setPixmap(mImages[0]); + if(mImages[0].hasAlpha()) { + setMask(*mImages[0].mask()); + } + resize(mImages[0].size()); +} + +void +JPushButton::pressImage() +{ + setPixmap(mImages[1]); + if(mImages[1].hasAlpha()) { + setMask(*mImages[1].mask()); + } + resize(mImages[1].size()); +} + +// Mouse button released +void +JPushButton::mousePressEvent(QMouseEvent *e) +{ + switch (e->button()) { + case Qt::LeftButton: + pressImage(); + break; + + default: + e->ignore(); + break; + } +} + +// Mouse button released +void +JPushButton::mouseReleaseEvent (QMouseEvent *e) { + switch (e->button()) { + case Qt::LeftButton: + if (this->rect().contains(e->pos())) { + if(mIsToggling) { + mIsPressed = !mIsPressed; + if(mIsPressed) { + press(); + } + else { + release(); + } + emit clicked(mIsPressed); + } + else { + release(); + emit clicked(); + } + } + else { + if(isPressed()) { + press(); + } + else { + release(); + } + } + break; + + default: + e->ignore(); + break; + } +} + +void +JPushButton::mouseMoveEvent(QMouseEvent *e) +{ + e->accept(); +} + diff --git a/src/gui/qt/JPushButton.hpp b/src/gui/qt/JPushButton.hpp new file mode 100644 index 0000000000..c71e3114bd --- /dev/null +++ b/src/gui/qt/JPushButton.hpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jerome Oufella (jerome.oufella@savoirfairelinux.com) + * + * Portions (c) Jean-Philippe Barrette-LaPierre + * (jean-philippe.barrette-lapierre@savoirfairelinux.com) + * Portions (c) Valentin Heinitz + * + * This 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, + * or (at your option) any later version. + * + * This 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. + * + * You should have received a copy of the GNU General Public + * License along with dpkg; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __J_PUSH_BUTTON_H__ +#define __J_PUSH_BUTTON_H__ + +#include <qlabel.h> +#include <qpixmap.h> +#include <qimage.h> + +/** + * This class Emulate a PushButton but takes two + * images to display its state. + */ +class JPushButton : public QLabel +{ + Q_OBJECT + +public: + JPushButton(const QString &released, + const QString &pressed, + QWidget *parent); + ~JPushButton(); + + bool isPressed() + {return mIsPressed;} + + static QPixmap transparize(const QString &image); + +public slots: + /** + * This function will switch the button + */ + virtual void press(); + virtual void release(); + + virtual void setToggle(bool toggled); + + private slots: + virtual void pressImage(); + virtual void releaseImage(); + +protected: + QPixmap mImages[2]; + bool mIsPressed; + +protected: + void mousePressEvent(QMouseEvent *); + void mouseReleaseEvent(QMouseEvent *); + void mouseMoveEvent(QMouseEvent *); + +signals: + void clicked(bool); + void clicked(); + +private: + bool mIsToggling; +}; + +#endif // defined(__J_PUSH_BUTTON_H__) diff --git a/src/gui/qt/Launcher.cpp b/src/gui/qt/Launcher.cpp new file mode 100644 index 0000000000..dd9b50573a --- /dev/null +++ b/src/gui/qt/Launcher.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "DebugOutput.hpp" +#include "Launcher.hpp" + +Launcher::Launcher() + : mProc(NULL) +{} + +Launcher::~Launcher() +{ + delete mProc; +} + +void +Launcher::start() +{ + if(!mProc) { + DebugOutput::instance() << QObject::tr("Launcher::start()\n"); + mProc = new QProcess(this); + mProc->addArgument("sflphoned"); + + connect(mProc, SIGNAL(processExited()), + this, SLOT(stop())); + connect(mProc, SIGNAL(readyReadStdout()), + this, SLOT(readOutput())); + connect(mProc, SIGNAL(readyReadStderr()), + this, SLOT(readError())); + + if(!mProc->start()) { + DebugOutput::instance() << tr("Launcher: Couldn't launch sflphoned.\n"); + emit error(); + } + else { + DebugOutput::instance() << tr("Launcher: sflphoned launched.\n"); + emit started(); + } + } +} + +void +Launcher::stop() +{ + if(mProc) { + mProc->kill(); + delete mProc; + mProc = NULL; + emit stopped(); + } +} + +void +Launcher::readOutput() +{ + if(mProc) { + //emit daemonOutputAvailable(mProc->readLineStdout()); + DebugOutput::instance() << tr("%1\n").arg(mProc->readLineStdout()); + } + else { + DebugOutput::instance() << tr("Launcher: Trying to read output without " + "a valid process.\n"); + } +} + +void +Launcher::readError() +{ + if(mProc) { + DebugOutput::instance() << tr("%1\n").arg(mProc->readLineStderr()); + } + else { + DebugOutput::instance() << tr("Launcher: Trying to read error without " + "a valid process.\n"); + } +} diff --git a/src/gui/qt/Launcher.hpp b/src/gui/qt/Launcher.hpp new file mode 100644 index 0000000000..346f10c840 --- /dev/null +++ b/src/gui/qt/Launcher.hpp @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __LAUNCHER_HPP__ +#define __LAUNCHER_HPP__ + +#include <qobject.h> +#include <qprocess.h> + +class Launcher : public QObject +{ + Q_OBJECT + +public: + Launcher(); + virtual ~Launcher(); + +signals: + void started(); + void stopped(); + void error(); + void daemonOutputAvailable(QString); + void daemonErrorAvailable(QString); + +public slots: + void start(); + void stop(); + void readOutput(); + void readError(); + +private: + QProcess *mProc; +}; + +#endif diff --git a/src/gui/qt/Makefile.am b/src/gui/qt/Makefile.am index d654bfcff8..5f62ad2270 100644 --- a/src/gui/qt/Makefile.am +++ b/src/gui/qt/Makefile.am @@ -1,9 +1,9 @@ libexec_PROGRAMS = sflphone-qt BUILT_SOURCES = \ - ./moc_ConfigurationPanel.cpp \ ./ConfigurationPanelui.cpp \ ./ConfigurationPanel.h \ + ./ConfigurationPanelmocpp.cpp \ ./ConfigurationManagerImplmoc.cpp \ ./ConfigurationPanelImplmoc.cpp \ ./JPushButtonmoc.cpp \ @@ -120,13 +120,14 @@ KDE_CXXFLAGS = $(USE_EXCEPTIONS) AM_CPPFLAGS = -I$(top_srcdir)/libs/ $(KDE_INCLUDES) $(QT_INCLUDES) $(X_INCLUDES) $(all_includes) AM_LDFLAGS = $(KDE_LDFLAGS) $(QT_LDFLAGS) $(X_LDFLAGS) $(all_libraries) + qmake_image_collection.cpp: $(IMAGES) $(UIC) -embed sflphone-qt $(IMAGES) -o $@ %.h: %.ui $(UIC) -o $@ $< -moc_%.cpp: %.h +%mocpp.cpp: %.h $(MOC) -o $@ $< %moc.cpp: %.hpp diff --git a/src/gui/qt/NumericKeypad.cpp b/src/gui/qt/NumericKeypad.cpp new file mode 100644 index 0000000000..0c688d851c --- /dev/null +++ b/src/gui/qt/NumericKeypad.cpp @@ -0,0 +1,265 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <string> +#include <utility> // for std::make_pair +#include <qapplication.h> +#include <qevent.h> + +#include "DebugOutput.hpp" +#include "NumericKeypad.hpp" + +#define PIXMAP_KEYPAD_IMAGE QString("dtmf_main.png") +#define DTMF_0_RELEASED_IMAGE QString("dtmf_0_off.png") +#define DTMF_0_PRESSED_IMAGE QString("dtmf_0_on.png") +#define DTMF_1_RELEASED_IMAGE QString("dtmf_1_off.png") +#define DTMF_1_PRESSED_IMAGE QString("dtmf_1_on.png") +#define DTMF_2_RELEASED_IMAGE QString("dtmf_2_off.png") +#define DTMF_2_PRESSED_IMAGE QString("dtmf_2_on.png") +#define DTMF_3_RELEASED_IMAGE QString("dtmf_3_off.png") +#define DTMF_3_PRESSED_IMAGE QString("dtmf_3_on.png") +#define DTMF_4_RELEASED_IMAGE QString("dtmf_4_off.png") +#define DTMF_4_PRESSED_IMAGE QString("dtmf_4_on.png") +#define DTMF_5_RELEASED_IMAGE QString("dtmf_5_off.png") +#define DTMF_5_PRESSED_IMAGE QString("dtmf_5_on.png") +#define DTMF_6_RELEASED_IMAGE QString("dtmf_6_off.png") +#define DTMF_6_PRESSED_IMAGE QString("dtmf_6_on.png") +#define DTMF_7_RELEASED_IMAGE QString("dtmf_7_off.png") +#define DTMF_7_PRESSED_IMAGE QString("dtmf_7_on.png") +#define DTMF_8_RELEASED_IMAGE QString("dtmf_8_off.png") +#define DTMF_8_PRESSED_IMAGE QString("dtmf_8_on.png") +#define DTMF_9_RELEASED_IMAGE QString("dtmf_9_off.png") +#define DTMF_9_PRESSED_IMAGE QString("dtmf_9_on.png") +#define DTMF_STAR_RELEASED_IMAGE QString("dtmf_star_off.png") +#define DTMF_STAR_PRESSED_IMAGE QString("dtmf_star_on.png") +#define DTMF_POUND_RELEASED_IMAGE QString("dtmf_pound_off.png") +#define DTMF_POUND_PRESSED_IMAGE QString("dtmf_pound_on.png") +#define DTMF_CLOSE_RELEASED_IMAGE QString("dtmf_close_off.png") +#define DTMF_CLOSE_PRESSED_IMAGE QString("dtmf_close_on.png") + +NumericKeypad::NumericKeypad() +//: TransparentWidget(PIXMAP_KEYPAD_IMAGE, NULL) + : QDialog(NULL, + "DTMF Keypad", + false, + Qt::WStyle_Customize) +{ + TransparentWidget::setPaletteBackgroundPixmap(this, PIXMAP_KEYPAD_IMAGE); + resize(TransparentWidget::retreive(PIXMAP_KEYPAD_IMAGE).size()); + this->setCaption("DTMF Keypad"); + //setMaximumSize(getSourceImage().width(), getSourceImage().height()); + + // Buttons initialisation + mKey0 = new JPushButton(DTMF_0_RELEASED_IMAGE, + DTMF_0_PRESSED_IMAGE, + this); + mKey1 = new JPushButton(DTMF_1_RELEASED_IMAGE, + DTMF_1_PRESSED_IMAGE, + this); + mKey2 = new JPushButton(DTMF_2_RELEASED_IMAGE, + DTMF_2_PRESSED_IMAGE, + this); + mKey3 = new JPushButton(DTMF_3_RELEASED_IMAGE, + DTMF_3_PRESSED_IMAGE, + this); + mKey4 = new JPushButton(DTMF_4_RELEASED_IMAGE, + DTMF_4_PRESSED_IMAGE, + this); + mKey5 = new JPushButton(DTMF_5_RELEASED_IMAGE, + DTMF_5_PRESSED_IMAGE, + this); + mKey6 = new JPushButton(DTMF_6_RELEASED_IMAGE, + DTMF_6_PRESSED_IMAGE, + this); + mKey7 = new JPushButton(DTMF_7_RELEASED_IMAGE, + DTMF_7_PRESSED_IMAGE, + this); + mKey8 = new JPushButton(DTMF_8_RELEASED_IMAGE, + DTMF_8_PRESSED_IMAGE, + this); + mKey9 = new JPushButton(DTMF_9_RELEASED_IMAGE, + DTMF_9_PRESSED_IMAGE, + this); + mKeyStar = new JPushButton(DTMF_STAR_RELEASED_IMAGE, + DTMF_STAR_PRESSED_IMAGE, + this); + mKeyHash = new JPushButton(DTMF_POUND_RELEASED_IMAGE, + DTMF_POUND_PRESSED_IMAGE, + this); + mKeyClose = new JPushButton(DTMF_CLOSE_RELEASED_IMAGE, + DTMF_CLOSE_PRESSED_IMAGE, + this); + connect(mKey0, SIGNAL(clicked()), + this, SLOT(dtmf0Click())); + connect(mKey1, SIGNAL(clicked()), + this, SLOT(dtmf1Click())); + connect(mKey2, SIGNAL(clicked()), + this, SLOT(dtmf2Click())); + connect(mKey3, SIGNAL(clicked()), + this, SLOT(dtmf3Click())); + connect(mKey4, SIGNAL(clicked()), + this, SLOT(dtmf4Click())); + connect(mKey5, SIGNAL(clicked()), + this, SLOT(dtmf5Click())); + connect(mKey6, SIGNAL(clicked()), + this, SLOT(dtmf6Click())); + connect(mKey7, SIGNAL(clicked()), + this, SLOT(dtmf7Click())); + connect(mKey8, SIGNAL(clicked()), + this, SLOT(dtmf8Click())); + connect(mKey9, SIGNAL(clicked()), + this, SLOT(dtmf9Click())); + connect(mKeyStar, SIGNAL(clicked()), + this, SLOT(dtmfStarClick())); + connect(mKeyHash, SIGNAL(clicked()), + this, SLOT(dtmfHashClick())); + + + mKey0->move(58, 157); + mKey1->move(12, 22); + mKey2->move(58, 22); + mKey3->move(104, 22); + mKey4->move(12, 67); + mKey5->move(58, 67); + mKey6->move(104, 67); + mKey7->move(12, 112); + mKey8->move(58, 112); + mKey9->move(104, 112); + mKeyStar->move(12, 157); + mKeyHash->move(104, 157); + mKeyClose->move(141,5); + + mKeys.insert(std::make_pair(Qt::Key_0, mKey0)); + mKeys.insert(std::make_pair(Qt::Key_1, mKey1)); + mKeys.insert(std::make_pair(Qt::Key_2, mKey2)); + mKeys.insert(std::make_pair(Qt::Key_3, mKey3)); + mKeys.insert(std::make_pair(Qt::Key_4, mKey4)); + mKeys.insert(std::make_pair(Qt::Key_5, mKey5)); + mKeys.insert(std::make_pair(Qt::Key_6, mKey6)); + mKeys.insert(std::make_pair(Qt::Key_7, mKey7)); + mKeys.insert(std::make_pair(Qt::Key_8, mKey8)); + mKeys.insert(std::make_pair(Qt::Key_9, mKey9)); + mKeys.insert(std::make_pair(Qt::Key_Asterisk, mKeyStar)); + mKeys.insert(std::make_pair(Qt::Key_NumberSign, mKeyHash)); + + connect(mKeyClose, SIGNAL(clicked()), + this, SLOT(hide())); + connect(mKeyClose, SIGNAL(clicked()), + this, SIGNAL(hidden())); +} + +NumericKeypad::~NumericKeypad() +{} + +void +NumericKeypad::keyReleaseEvent (QKeyEvent* e) { + std::map< Qt::Key, JPushButton * >::iterator pos = mKeys.find(Qt::Key(e->key())); + if(pos != mKeys.end()) { + QMouseEvent me(QEvent::MouseButtonRelease, + QPoint(0,0), + Qt::LeftButton, + Qt::LeftButton); + QApplication::sendEvent(pos->second, + &me); + } +} + +void +NumericKeypad::keyPressEvent (QKeyEvent* e) { + //QApplication::sendEvent(QApplication::mainWindow, e); + // TODO: Key appears pressed when done. + std::map< Qt::Key, JPushButton * >::iterator pos = mKeys.find(Qt::Key(e->key())); + if(pos != mKeys.end()) { + QMouseEvent me(QEvent::MouseButtonPress, + QPoint(0,0), + Qt::LeftButton, + Qt::LeftButton); + QApplication::sendEvent(pos->second, + &me); + } + else { + emit keyPressed(Qt::Key(e->key())); + } +} + + +void +NumericKeypad::mousePressEvent(QMouseEvent *e) +{ + mLastPos = e->pos(); +} + +void +NumericKeypad::mouseMoveEvent(QMouseEvent *e) +{ + // Note that moving the windows is very slow + // 'cause it redraw the screen each time. + // Usually it doesn't. We could do it by a timer. + move(e->globalPos() - mLastPos); +} + +void +NumericKeypad::dtmf0Click() +{ + emit keyPressed(Qt::Key_0); +} + +void +NumericKeypad::dtmf1Click() +{emit keyPressed(Qt::Key_1);} + +void +NumericKeypad::dtmf2Click() +{emit keyPressed(Qt::Key_2);} + +void +NumericKeypad::dtmf3Click() +{emit keyPressed(Qt::Key_3);} + +void +NumericKeypad::dtmf4Click() +{emit keyPressed(Qt::Key_4);} + +void +NumericKeypad::dtmf5Click() +{emit keyPressed(Qt::Key_5);} + +void +NumericKeypad::dtmf6Click() +{emit keyPressed(Qt::Key_6);} + +void +NumericKeypad::dtmf7Click() +{emit keyPressed(Qt::Key_7);} + +void +NumericKeypad::dtmf8Click() +{emit keyPressed(Qt::Key_8);} + +void +NumericKeypad::dtmf9Click() +{emit keyPressed(Qt::Key_9);} + +void +NumericKeypad::dtmfStarClick() +{emit keyPressed(Qt::Key_Asterisk);} + +void +NumericKeypad::dtmfHashClick() +{emit keyPressed(Qt::Key_NumberSign);} diff --git a/src/gui/qt/NumericKeypad.hpp b/src/gui/qt/NumericKeypad.hpp new file mode 100644 index 0000000000..8f0557a1e7 --- /dev/null +++ b/src/gui/qt/NumericKeypad.hpp @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __NUMERIC_KEYPAD_HPP__ +#define __NUMERIC_KEYPAD_HPP__ + +#include <map> +#include <qdialog.h> +#include <qpoint.h> + +#include "JPushButton.hpp" +#include "TransparentWidget.hpp" + +class NumericKeypad : public QDialog +{ + Q_OBJECT +public: + // Default Constructor and destructor + NumericKeypad(); + ~NumericKeypad(); + + JPushButton *mKey0; + JPushButton *mKey1; + JPushButton *mKey2; + JPushButton *mKey3; + JPushButton *mKey4; + JPushButton *mKey5; + JPushButton *mKey6; + JPushButton *mKey7; + JPushButton *mKey8; + JPushButton *mKey9; + JPushButton *mKeyStar; + JPushButton *mKeyHash; + JPushButton *mKeyClose; + +public slots: + void mousePressEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void keyPressEvent(QKeyEvent *e); + void keyReleaseEvent(QKeyEvent *e); + + void dtmf0Click(); + void dtmf1Click(); + void dtmf2Click(); + void dtmf3Click(); + void dtmf4Click(); + void dtmf5Click(); + void dtmf6Click(); + void dtmf7Click(); + void dtmf8Click(); + void dtmf9Click(); + void dtmfStarClick(); + void dtmfHashClick(); + +signals: + void keyPressed(Qt::Key k); + void hidden(); + +private: + QPoint mLastPos; + std::map< Qt::Key, JPushButton * > mKeys; +}; + +#endif // __NUMERIC_KEYPAD_H__ diff --git a/src/gui/qt/ObjectFactory.hpp b/src/gui/qt/ObjectFactory.hpp new file mode 100644 index 0000000000..4cb8dd0a01 --- /dev/null +++ b/src/gui/qt/ObjectFactory.hpp @@ -0,0 +1,98 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef SFLPHONEGUI_OBJECTFACTORY_H +#define SFLPHONEGUI_OBJECTFACTORY_H + +#include <list> +#include <map> +#include <qstring.h> + +/** + * This is the base class that we will use to + * create an object from the "create" function. + */ +template< typename Base > +class ObjectCreatorBase +{ + public: + virtual ~ObjectCreatorBase(){} + virtual Base *create(const QString &command, + const QString &sequenceId, + const std::list< QString > &args) = 0; + + virtual ObjectCreatorBase *clone() = 0; +}; + +/** + * This is the actual class that will create + * the request. It will return a Request + */ +template< typename Base, typename Actual > + class ObjectCreator : public ObjectCreatorBase< Base > +{ + public: + virtual Actual *create(const QString &command, + const QString &sequenceId, + const std::list< QString > &args); + + virtual ObjectCreatorBase< Base > *clone(); +}; + + +/** + * This class is used to create object related to + * a string. However, thoses objects will be created + * with the default constructor. + */ +template< typename Base > +class ObjectFactory +{ +public: + ObjectFactory(); + + /** + * Ask for a new object linked to the string. + */ + Base *create(const QString &requestname, + const QString &sequenceId, + const std::list< QString > &args); + + /** + * Register the string to return a Actual type. + */ + template< typename Actual > + void registerObject(const QString &name); + + /** + * Register the default object to be created, + * when the object wanted isn't registered. + */ + template< typename Actual > + void registerDefaultObject(); + + private: + std::map< QString, ObjectCreatorBase< Base > * > mObjectCreators; + ObjectCreatorBase< Base > *mDefaultObjectCreator; +}; + +#include "ObjectFactory.inl" + +#endif diff --git a/src/gui/qt/ObjectFactory.inl b/src/gui/qt/ObjectFactory.inl new file mode 100644 index 0000000000..09a5e643d1 --- /dev/null +++ b/src/gui/qt/ObjectFactory.inl @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef SFLPHONEGUI_OBJECTFACTORY_INL +#define SFLPHONEGUI_OBJECTFACTORY_INL + +#include <qobject.h> +#include <stdexcept> + +#include "DebugOutput.hpp" + +template< typename Base, typename Actual > +Actual * +ObjectCreator< Base, Actual >::create(const QString &command, + const QString &sequenceId, + const std::list< QString > &args) +{ + return new Actual(sequenceId, command, args); +} + +template< typename Base, typename Actual > +ObjectCreatorBase< Base > * +ObjectCreator< Base, Actual >::clone() +{ + return new ObjectCreator< Base, Actual >(); +} + +template< typename Base > +ObjectFactory< Base >::ObjectFactory() + : mDefaultObjectCreator(NULL) +{} + +template< typename Base > +Base * +ObjectFactory< Base >::create(const QString &command, + const QString &sequenceId, + const std::list< QString > &args) +{ + typename std::map< QString, ObjectCreatorBase< Base > * >::iterator pos = mObjectCreators.find(command); + if(pos == mObjectCreators.end()) { + if(!mDefaultObjectCreator) { + throw std::logic_error("ObjectFactory: You need to specify a default creator.\n"); + } + + return mDefaultObjectCreator->create(command, sequenceId, args); + } + + return pos->second->create(command, sequenceId, args); +} + +template< typename Base > +template< typename Actual > +void +ObjectFactory< Base >::registerObject(const QString &name) +{ + if(mObjectCreators.find(name) != mObjectCreators.end()) { + delete mObjectCreators[name]; + } + + mObjectCreators[name] = new ObjectCreator< Base, Actual >(); +} + +template< typename Base > +template< typename Actual > +void +ObjectFactory< Base >::registerDefaultObject() +{ + if(mDefaultObjectCreator) { + delete mDefaultObjectCreator; + } + + mDefaultObjectCreator = new ObjectCreator< Base, Actual >(); +} + + +#endif + diff --git a/src/gui/qt/ObjectPool.hpp b/src/gui/qt/ObjectPool.hpp new file mode 100644 index 0000000000..612161f9e5 --- /dev/null +++ b/src/gui/qt/ObjectPool.hpp @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef SFLPHONEGUI_OBJECTPOOL_H +#define SFLPHONEGUI_OBJECTPOOL_H + +#include <list> +#include <qstring.h> +#include <QMutex> +#include <QWaitCondition> + +template< typename T > +class ObjectPool +{ + public: + /** + * This function will push a line in the pool. + */ + void push(const T &line); + + /** + * This function will wait for an available line. + */ + bool pop(T &value, unsigned long time = ULONG_MAX); + + private: + std::list< T > mPool; + + QMutex mMutex; + QWaitCondition mDataAvailable; +}; + +#include "ObjectPool.inl" + +#endif + diff --git a/src/gui/qt/ObjectPool.inl b/src/gui/qt/ObjectPool.inl new file mode 100644 index 0000000000..b389eb92b1 --- /dev/null +++ b/src/gui/qt/ObjectPool.inl @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef SFLPHONEGUI_OBJECTPOOL_INL +#define SFLPHONEGUI_OBJECTPOOL_INL + +template< typename T > +void +ObjectPool< T >::push(const T &value) +{ + QMutexLocker guard(&mMutex); + mPool.push_back(value); + mDataAvailable.wakeOne(); +} + +template< typename T > +bool +ObjectPool< T >::pop(T &value, unsigned long time) +{ + QMutexLocker guard(&mMutex); + mDataAvailable.wait(guard.mutex(), time); + + if(mPool.begin() == mPool.end()) { + return false; + } + else { + typename std::list< T >::iterator pos = mPool.begin(); + mPool.pop_front(); + value = (*pos); + return true; + } +} + +#endif diff --git a/src/gui/qt/PhoneLine.cpp b/src/gui/qt/PhoneLine.cpp new file mode 100644 index 0000000000..03cae78988 --- /dev/null +++ b/src/gui/qt/PhoneLine.cpp @@ -0,0 +1,435 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <iostream> + +#include "globals.h" +#include "Call.hpp" +#include "DebugOutput.hpp" +#include "PhoneLine.hpp" +#include "Request.hpp" + +PhoneLine::PhoneLine(const Session &session, + const Account &account, + unsigned int line) + : mSession(session) + , mAccount(account) + , mCall(NULL) + , mLine(line) + , mSelected(false) + , mLineStatus("test") + , mActionTimer(new QTimer(this)) + , mTalking(false) + , mIsOnError(false) + , mIsTransfering(false) +{ + QObject::connect(mActionTimer, SIGNAL(timeout()), + this, SLOT(resetAction())); + QObject::connect(this, SIGNAL(transfered()), + this, SLOT(finishTransfer())); +} + +PhoneLine::~PhoneLine() +{ + clearCall(); +} + +void +PhoneLine::clearCall() +{ + if(mCall) { + delete mCall; + mCall = NULL; + } + + clearPeer(); +} + +void +PhoneLine::setCall(const Call &call) +{ + setCall(new Call(call)); +} + +void +PhoneLine::setCall(Call *call) +{ + clearCall(); + + mCall = call; + setPeer(mCall->peer()); +} + + +void +PhoneLine::setPeer(const QString &peer) +{ + mPeer = peer; + emit peerUpdated(peer); +} + +void +PhoneLine::clearPeer() +{ + mPeer = ""; + emit peerCleared(); +} + +QString +PhoneLine::getLineStatus() +{ + return mLineStatus; +} + +void +PhoneLine::resetAction() +{ + setAction(""); +} + +void +PhoneLine::setLineStatus(QString status) +{ + mActionTimer->stop(); + mAction = ""; + + mLineStatus = status; + emit lineStatusChanged(mLineStatus); +} + +void +PhoneLine::setAction(QString status) +{ + mActionTimer->stop(); + mAction = status; + emit actionChanged(mAction); +} + +void +PhoneLine::setTempAction(QString status) +{ + mActionTimer->stop(); + mActionTimer->start(3000); + mAction = status; + emit actionChanged(mAction); +} + +unsigned int +PhoneLine::line() +{ + return mLine; +} + +void +PhoneLine::lock() +{ + //mPhoneLineMutex.lock(); +} + +void +PhoneLine::unlock() +{ + //mPhoneLineMutex.unlock(); +} + +void +PhoneLine::select(bool hardselect) +{ + if(!mSelected) { + mSelected = true; + + if(!hardselect) { + if(mCall) { + if(mIsOnError) { + close(); + } + else if(mCall->isIncomming()) { + answer(); + } + else { + unhold(); + } + } + else { + setLineStatus(QObject::tr("Ready.")); + setAction(""); + } + } + + emit selected(true); + } + +} + +void +PhoneLine::disconnect() +{ + mSelected = false; + close(); + + emit selected(false); +} + +void +PhoneLine::close() +{ + clearCall(); + mIsOnError = false; +} + +void +PhoneLine::error(QString message) +{ + setLineStatus(message); + mIsOnError = true; +} + +void +PhoneLine::unselect(bool hardselect) +{ + DebugOutput::instance() << tr("PhoneLine %1: I am unselected.\n").arg(mLine); + setAction(""); + mSelected = false; + if(mIsOnError) { + close(); + } + + if(mCall) { + if(!hardselect) { + mCall->hold(); + } + emit backgrounded(); + } + else { + emit selected(false); + } +} + +void +PhoneLine::incomming(const Call &call) +{ + if(mCall) { + DebugOutput::instance() << tr("PhoneLine %1: Trying to set a phone line to an active call.\n").arg(mLine); + } + else { + setCall(call); + emit backgrounded(); + } +} + +void +PhoneLine::clear() +{ + mBuffer = ""; + emit bufferStatusChanged(mBuffer); +} + +void +PhoneLine::sendKey(Qt::Key c) +{ + DebugOutput::instance() << tr("PhoneLine %1: Received the character:%2.\n") + .arg(mLine) + .arg(c); + switch(c) { + case Qt::Key_Enter: + case Qt::Key_Return: + if(!mCall) { + return call(); + } + if(mCall && mIsTransfering) { + return transfer(); + } + break; + + case Qt::Key_Backspace: + if((!mCall || mIsTransfering) && mBuffer.length() > 0) { + mBuffer.remove(mBuffer.length() - 1, 1); + emit bufferStatusChanged(mBuffer); + } + break; + + default: + if(!mCall || mIsTransfering) { + mBuffer += c; + emit bufferStatusChanged(mBuffer); + } + + if (QChar(c).isDigit() || c == Qt::Key_Asterisk || c == Qt::Key_NumberSign) { + if(!mCall) { + mSession.playDtmf(c); + } + else { + mCall->sendDtmf(c); + } + } + } +} + +void +PhoneLine::call() +{ + if(mBuffer.length()) { + call(mBuffer); + } +} + +void +PhoneLine::call(const QString &to) +{ + DebugOutput::instance() << tr("PhoneLine %1: Calling %2.\n").arg(mLine).arg(to); + if(!mCall) { + setLineStatus(tr("Calling %1...").arg(to)); + Call *call; + Request *r = mAccount.createCall(call, to); + // entry + connect(r, SIGNAL(entry(QString, QString)), + this, SLOT(setLineStatus(QString))); + + connect(r, SIGNAL(error(QString, QString)), + this, SLOT(error(QString))); + + connect(r, SIGNAL(success(QString, QString)), + this, SLOT(setTalkingState())); + + setCall(call); + clear(); + } +} + +void +PhoneLine::setTalkingState() +{ + mTalking = true; + mTalkingTime.start(); + talkingStarted(mTalkingTime); + setLineStatus(tr("Talking to: %1").arg(mPeer)); + setAction(""); +} + +void +PhoneLine::transfer() +{ + if(mCall) { + if(mBuffer.length() == 0) { + DebugOutput::instance() << tr("PhoneLine %1: We're now in transfer mode.\n"); + setAction(tr("Transfer to:")); + clear(); + unselect(); + mIsTransfering = true; + } + else { + DebugOutput::instance() << tr("PhoneLine %1: Trying to transfer to \"%2\".\n") + .arg(mLine) + .arg(mBuffer); + connect(mCall->transfer(mBuffer), SIGNAL(success(QString, QString)), + this, SIGNAL(transfered())); + clear(); + + unselect(true); + } + } +} + +void +PhoneLine::finishTransfer() +{ + clearCall(); + stopTalking(); + + if(mIsTransfering) { + mIsTransfering = false; + emit transfered(); + } +} + +void +PhoneLine::hold() +{ + if(mCall) { + setAction(tr("Holding...")); + DebugOutput::instance() << tr("PhoneLine %1: Trying to Hold.\n").arg(mLine); + mCall->hold(); + } + + unselect(); +} + +void +PhoneLine::unhold() +{ + if(mCall) { + setAction("Unholding..."); + DebugOutput::instance() << tr("PhoneLine %1: Trying to Unhold.\n").arg(mLine); + mCall->unhold(); + } +} + +void +PhoneLine::answer() +{ + if(mCall) { + setAction("Answering..."); + DebugOutput::instance() << tr("PhoneLine %1: Trying to answer.\n").arg(mLine); + mCall->answer(); + } +} + +void +PhoneLine::stopTalking() +{ + mTalking = false; + emit talkingStopped(); +} + +void +PhoneLine::hangup(bool sendrequest) +{ + stopTalking(); + + if(sendrequest) { + setAction(tr("Hanguping...")); + } + else { + setAction(tr("Hanguped.")); + } + + if(mCall) { + if(sendrequest) { + mCall->hangup(); + } + clearCall(); + } + + clear(); + clearPeer(); + unselect(); +} + +QString +PhoneLine::getCallId() +{ + QString id; + if(mCall) { + id = mCall->id(); + } + + return id; +} + diff --git a/src/gui/qt/PhoneLine.hpp b/src/gui/qt/PhoneLine.hpp new file mode 100644 index 0000000000..2a390585e2 --- /dev/null +++ b/src/gui/qt/PhoneLine.hpp @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qobject.h> +#include <qstring.h> +#include <qtimer.h> +#include <qdatetime.h> + +#include "Account.hpp" +#include "Session.hpp" + +class Call; + +class PhoneLine : public QObject +{ + Q_OBJECT + +public: + PhoneLine(const Session &session, + const Account &account, + unsigned int line); + ~PhoneLine(); + + void call(const QString &to); + void call(); + void answer(); + void hangup(bool sendrequest = true); + void hold(); + void unhold(); + + QString getCallId(); + + unsigned int line(); + + /** + * This will lock the current phone line. + * + * Note: this will only lock the phone line + * for those that uses this lock, unlock + * mechanism. PhoneLineManager always uses + * this mechanism. So, if you work only with + * PhoneLineManager, it will be thread safe. + */ + void lock(); + + /** + * This will unlock the current phone line. + * See the Note of the lock function. + */ + void unlock(); + + + /** + * This function will return true if there's no + * activity on this line. It means that even + * if we typed something on this line, but haven't + * started any communication, this will be available. + */ + bool isAvailable() + {return !mCall;} + + bool isTalking() + {return mTalking;} + + void sendKey(Qt::Key c); + + QTime getTalkingTime() + {return mTalkingTime;} + + QString getLineStatus(); + QString getBuffer() + {return mBuffer;} + +public slots: + void setLineStatus(QString); + void setAction(QString); + void setTempAction(QString); + void resetAction(); + void incomming(const Call &call); + + /** + * Clears the buffer of the line. + */ + void clear(); + + /** + * The user selected this line. + */ + void select(bool hardselect = false); + + /** + * This phoneline is no longer selected. + */ + void unselect(bool hardselect = false); + + /** + * This will do a hard unselect. it means it + * will remove the call if there's one. + */ + void disconnect(); + + /** + * This will close the current call. it means it + * will remove the call if there's one. + */ + void close(); + + /** + * This will close the current call. it means it + * will remove the call if there's one. The line + * will be in an error state. + */ + void error(QString); + + /** + * This function will put the line on hold + * and will wait for the numbre to compose. + */ + void transfer(); + + void finishTransfer(); + + void setPeer(const QString &peer); + void clearPeer(); + void setState(const QString &){} + + void setTalkingState(); + void stopTalking(); + +signals: + void selected(bool); + void backgrounded(); + void lineStatusChanged(QString); + void actionChanged(QString); + void bufferStatusChanged(QString); + void peerUpdated(QString); + void peerCleared(); + void talkingStarted(QTime); + void talkingStopped(); + void transfered(); + +private: + void setCall(Call *call); + void setCall(const Call &call); + void clearCall(); + + + Session mSession; + Account mAccount; + Call *mCall; + unsigned int mLine; + + bool mSelected; + bool mInUse; + //This is the buffer when the line is not in use; + QString mBuffer; + + QString mLineStatus; + QString mAction; + QTimer *mActionTimer; + QTime mTalkingTime; + bool mTalking; + QString mPeer; + + bool mIsOnError; + bool mIsTransfering; +}; diff --git a/src/gui/qt/PhoneLineButton.cpp b/src/gui/qt/PhoneLineButton.cpp new file mode 100644 index 0000000000..cde6e3aee6 --- /dev/null +++ b/src/gui/qt/PhoneLineButton.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "globals.h" + +#include "PhoneLineButton.hpp" + +#include <qevent.h> +#include <qtimer.h> +#include <qtooltip.h> +#include <qpainter.h> + + +PhoneLineButton::PhoneLineButton(unsigned int line, + QWidget *parent) + : QPushButton(parent) + , mLine(line) + , mFace(0) +{ + setName(QObject::tr("line%1").arg(line)); + setToggleButton(true); + mTimer = new QTimer(this); + connect(mTimer, SIGNAL(timeout()), + this, SLOT(swap())); + connect(this, SIGNAL(clicked()), + this, SLOT(sendClicked())); +} + +void +PhoneLineButton::setToolTip(QString tip) +{ + QToolTip::add(this, tip); +} + +void +PhoneLineButton::swap() +{ + toggle(); +} + +void +PhoneLineButton::clearToolTip() +{ + QToolTip::remove(this); +} + +void +PhoneLineButton::suspend() +{ + setDown(false); + mTimer->start(500); +} + +void +PhoneLineButton::sendClicked() +{ + if(isOn()) { + emit selected(mLine); + } + else { + emit unselected(mLine); + } +} + diff --git a/src/gui/qt/PhoneLineButton.hpp b/src/gui/qt/PhoneLineButton.hpp new file mode 100644 index 0000000000..966c8ef31c --- /dev/null +++ b/src/gui/qt/PhoneLineButton.hpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef __PHONELINEBUTTON_HPP__ +#define __PHONELINEBUTTON_HPP__ + +#include <qlabel.h> +#include <qobject.h> +#include <qpixmap.h> +#include <qpushbutton.h> + +class QTimer; + + +/** + * This class Emulate a PushButton but takes two + * images to display its state. + */ +class PhoneLineButton : public QPushButton +{ + Q_OBJECT + +public: + PhoneLineButton(unsigned int line, + QWidget *parent); + + virtual ~PhoneLineButton(){} + +signals: + void selected(unsigned int); + void unselected(unsigned int); + +public slots: + virtual void suspend(); + virtual void setToolTip(QString); + virtual void clearToolTip(); + virtual void swap(); + virtual void sendClicked(); + +private: + unsigned int mLine; + QTimer *mTimer; + unsigned int mFace; + +}; + +#endif // defined(__J_PUSH_BUTTON_H__) diff --git a/src/gui/qt/PhoneLineLocker.cpp b/src/gui/qt/PhoneLineLocker.cpp new file mode 100644 index 0000000000..c6092c359b --- /dev/null +++ b/src/gui/qt/PhoneLineLocker.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "PhoneLineLocker.hpp" +#include "PhoneLine.hpp" + +PhoneLineLocker::PhoneLineLocker(PhoneLine *line, bool lock) + : mPhoneLine(line) +{ + if(mPhoneLine && lock) { + mPhoneLine->lock(); + } +} + +PhoneLineLocker::~PhoneLineLocker() +{ + if(mPhoneLine) { + mPhoneLine->unlock(); + } +} + + diff --git a/src/gui/qt/PhoneLineLocker.hpp b/src/gui/qt/PhoneLineLocker.hpp new file mode 100644 index 0000000000..f28f369198 --- /dev/null +++ b/src/gui/qt/PhoneLineLocker.hpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef SFLPHONEGUI_PHONELINELOCKER_HPP +#define SFLPHONEGUI_PHONELINELOCKER_HPP + +class PhoneLine; + +/** + * This class is used as a Lock. It means + * that it will lock a phone line on its + * constructor, and unlock it in its + * destructor. This is generaly used to + * be exception safe. + */ +class PhoneLineLocker +{ +public: + /** + * Retreive the "line" PhoneLine and + * locks it. + */ + PhoneLineLocker(PhoneLine *line, bool lock = true); + + /** + * Unlock the currently locked PhoneLine. + */ + ~PhoneLineLocker(); + +private: + PhoneLine *mPhoneLine; +}; + +#endif diff --git a/src/gui/qt/PhoneLineManager.hpp b/src/gui/qt/PhoneLineManager.hpp new file mode 100644 index 0000000000..c9a02c5f0a --- /dev/null +++ b/src/gui/qt/PhoneLineManager.hpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author : Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __PHONELINEMANAGER_HPP__ +#define __PHONELINEMANAGER_HPP__ + +#include "utilspp/Singleton.hpp" +#include "PhoneLineManagerImpl.hpp" + +typedef utilspp::SingletonHolder< PhoneLineManagerImpl > PhoneLineManager; + +#endif + diff --git a/src/gui/qt/PhoneLineManagerImpl.cpp b/src/gui/qt/PhoneLineManagerImpl.cpp new file mode 100644 index 0000000000..e034c9ec87 --- /dev/null +++ b/src/gui/qt/PhoneLineManagerImpl.cpp @@ -0,0 +1,750 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Yan Morin <yan.morin@savoirfairelinux.com> + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <iostream> +#include <stdexcept> + +#include "globals.h" + +#include "CallStatusFactory.hpp" +#include "ConfigurationManager.hpp" +#include "SFLEvents.hpp" +#include "SFLCallStatus.hpp" +#include "PhoneLine.hpp" +#include "PhoneLineLocker.hpp" +#include "PhoneLineManager.hpp" +#include "Request.hpp" + +#include <qmessagebox.h> + +PhoneLineManagerImpl::PhoneLineManagerImpl() + : mSession(NULL) + , mAccount(NULL) + , mCurrentLine(NULL) + , mIsInitialized(false) + , mVolume(-1) + , mMicVolume(-1) + , mIsConnected(false) + , mIsStopping(false) + , mLastNumber("") +{ + EventFactory::instance().registerDefaultEvent< DefaultEvent >(); + // TODO: 000 + EventFactory::instance().registerEvent< CallRelatedEvent >("000"); + EventFactory::instance().registerEvent< IncommingEvent >("001"); + EventFactory::instance().registerEvent< HangupEvent >("002"); + // TODO: 020 + EventFactory::instance().registerEvent< LoadSetupEvent >("010"); + EventFactory::instance().registerEvent< CallRelatedEvent >("020"); + EventFactory::instance().registerEvent< VolumeEvent >("021"); + EventFactory::instance().registerEvent< MicVolumeEvent >("022"); + EventFactory::instance().registerEvent< MessageTextEvent >("030"); + EventFactory::instance().registerEvent< TryingStatus >("110"); + EventFactory::instance().registerEvent< RingingStatus >("111"); + EventFactory::instance().registerEvent< HoldStatus >("112"); + EventFactory::instance().registerEvent< EstablishedStatus >("113"); + EventFactory::instance().registerEvent< BusyStatus >("114"); + EventFactory::instance().registerEvent< CongestionStatus >("115"); + EventFactory::instance().registerEvent< WrongNumberStatus >("116"); + QObject::connect(this, SIGNAL(disconnected()), + this, SLOT(closeSession())); + QObject::connect(this, SIGNAL(readyToHandleEvents()), + this, SLOT(handleEvents())); + QObject::connect(this, SIGNAL(connected()), + this, SIGNAL(readyToSendStatus())); + QObject::connect(this, SIGNAL(readyToSendStatus()), + this, SLOT(startSession())); + +} + +PhoneLineManagerImpl::~PhoneLineManagerImpl() +{ + delete mSession; + delete mAccount; + for(std::vector< PhoneLine * >::iterator pos = mPhoneLines.begin(); + pos != mPhoneLines.end(); + pos++) { + delete *pos; + } +} + + +void +PhoneLineManagerImpl::hasDisconnected() +{ + if(!mIsStopping) { + emit disconnected(); + } + else { + emit stopped(); + } +} + +void +PhoneLineManagerImpl::initialize(const Session &session) +{ + if(!mIsInitialized) { + mIsInitialized = true; + mSession = new Session(session); + mAccount = new Account(mSession->getDefaultAccount()); + } +} + +void PhoneLineManagerImpl::isInitialized() +{ + if(!mIsInitialized) { + throw std::logic_error("Trying to use PhoneLineManager without prior initialize."); + } +} + +void +PhoneLineManagerImpl::connect() +{ + isInitialized(); + + emit globalStatusSet(QString(tr("Trying to connect to sflphone server.."))); + mSession->connect(); +} + +void +PhoneLineManagerImpl::registerToServer() +{ + isInitialized(); + + Request *r = mSession->registerToServer(); + QObject::connect(r, SIGNAL(success()), + this, SIGNAL(registered())); +} + +void +PhoneLineManagerImpl::stop() +{ + isInitialized(); + + emit globalStatusSet(QString(tr("Stopping sflphone server.."))); + mIsStopping = true; + if(mIsConnected) { + mSession->stop(); + } + else { + emit stopped(); + } +} + +void +PhoneLineManagerImpl::startSession() +{ + isInitialized(); + + closeSession(); + + mIsConnected = true; + emit globalStatusSet(QString(tr("Trying to get line status..."))); + mSession->getCallStatus(); +} + +void +PhoneLineManagerImpl::handleEvents() +{ + isInitialized(); + + emit globalStatusSet(QString(tr("Welcome to SFLPhone"))); + mSession->getEvents(); + + Request *r; + r = mSession->list("ringtones"); + QObject::connect(r, SIGNAL(parsedEntry(QString, QString, QString, QString, QString)), + &ConfigurationManager::instance(), SLOT(addRingtone(QString, QString))); + QObject::connect(r, SIGNAL(success(QString, QString)), + &ConfigurationManager::instance(), SIGNAL(ringtonesUpdated())); + + r = mSession->list("audiodevice"); + QObject::connect(r, SIGNAL(parsedEntry(QString, QString, QString, QString, QString)), + &ConfigurationManager::instance(), SLOT(addAudioDevice(QString, + QString, + QString))); + QObject::connect(r, SIGNAL(success(QString, QString)), + &ConfigurationManager::instance(), SIGNAL(audioDevicesUpdated())); + + r = mSession->list("codecdescriptor"); + QObject::connect(r, SIGNAL(parsedEntry(QString, QString, QString, QString, QString)), + &ConfigurationManager::instance(), SLOT(addCodec(QString, QString))); + QObject::connect(r, SIGNAL(success(QString, QString)), + &ConfigurationManager::instance(), SIGNAL(codecsUpdated())); + + emit handleEventsSent(); +} + + +void +PhoneLineManagerImpl::closeSession() +{ + isInitialized(); + + mCurrentLine = NULL; + mIsConnected = false; + + unsigned int i = 0; + while(i < mPhoneLines.size()) { + mPhoneLines[i]->disconnect(); + i++; + } + + emit lineStatusSet(""); + emit bufferStatusSet(""); + emit actionSet(""); + emit globalStatusSet("Disconnected."); +} + + +PhoneLine * +PhoneLineManagerImpl::getCurrentLine() +{ + isInitialized(); + + return mCurrentLine; +} + +void +PhoneLineManagerImpl::setNbLines(unsigned int nb) +{ + isInitialized(); + + mPhoneLines.clear(); + for(unsigned int i = 0; i < nb; i++) { + PhoneLine *p = new PhoneLine(*mSession, *mAccount, i + 1); + QObject::connect(p, SIGNAL(lineStatusChanged(QString)), + this, SIGNAL(unselectedLineStatusSet(QString))); + mPhoneLines.push_back(p); + } +} + +PhoneLine * +PhoneLineManagerImpl::getNextAvailableLine() +{ + isInitialized(); + + PhoneLine *selectedLine = NULL; + PhoneLine *current = mCurrentLine; + + + unsigned int i = 0; + while(i < mPhoneLines.size() && !selectedLine) { + if(mPhoneLines[i]->isAvailable() && + mPhoneLines[i] != current) { + selectedLine = mPhoneLines[i]; + } + else { + i++; + } + } + + return selectedLine; +} + +PhoneLine * +PhoneLineManagerImpl::getLine(const Call &call) +{ + isInitialized(); + + PhoneLine *selectedLine = NULL; + + unsigned int i = 0; + while(i < mPhoneLines.size() && !selectedLine) { + if(mPhoneLines[i]->getCallId() == call.id()) { + selectedLine = mPhoneLines[i]; + } + else { + i++; + } + } + + return selectedLine; +} + +PhoneLine * +PhoneLineManagerImpl::getLine(unsigned int line) +{ + isInitialized(); + + PhoneLine *selectedLine = NULL; + + if(line < mPhoneLines.size()) { + selectedLine = mPhoneLines[line]; + } + + return selectedLine; +} + +void +PhoneLineManagerImpl::select(PhoneLine *line, bool hardselect) +{ + if(line && (mCurrentLine != line)) { + unselect(); + + QObject::disconnect(line, SIGNAL(lineStatusChanged(QString)), + this, SIGNAL(unselectedLineStatusSet(QString))); + QObject::connect(line, SIGNAL(lineStatusChanged(QString)), + this, SIGNAL(lineStatusSet(QString))); + QObject::connect(line, SIGNAL(actionChanged(QString)), + this, SIGNAL(actionSet(QString))); + QObject::connect(line, SIGNAL(bufferStatusChanged(QString)), + this, SIGNAL(bufferStatusSet(QString))); + QObject::connect(line, SIGNAL(talkingStarted(QTime)), + this, SIGNAL(talkingStarted(QTime))); + QObject::connect(line, SIGNAL(talkingStopped()), + this, SIGNAL(talkingStopped())); + QObject::connect(line, SIGNAL(transfered()), + this, SLOT(unselect())); + + + mCurrentLine = line; + mCurrentLine->select(hardselect); + if(mCurrentLine->isAvailable() && !hardselect) { + mSession->playTone(); + } + if(mCurrentLine->isTalking()) { + emit talkingStarted(mCurrentLine->getTalkingTime()); + } + emit lineStatusSet(mCurrentLine->getLineStatus()); + emit bufferStatusSet(mCurrentLine->getBuffer()); + } +} + +void +PhoneLineManagerImpl::unselect() +{ + if(mCurrentLine) { + QObject::disconnect(mCurrentLine, SIGNAL(lineStatusChanged(QString)), + this, SIGNAL(lineStatusSet(QString))); + QObject::disconnect(mCurrentLine, SIGNAL(actionChanged(QString)), + this, SIGNAL(actionSet(QString))); + QObject::disconnect(mCurrentLine, SIGNAL(bufferStatusChanged(QString)), + this, SIGNAL(bufferStatusSet(QString))); + QObject::disconnect(mCurrentLine, SIGNAL(talkingStarted(QTime)), + this, SIGNAL(talkingStarted(QTime))); + QObject::disconnect(mCurrentLine, SIGNAL(talkingStopped()), + this, SIGNAL(talkingStopped())); + QObject::disconnect(mCurrentLine, SIGNAL(transfered()), + this, SLOT(unselect())); + QObject::connect(mCurrentLine, SIGNAL(lineStatusChanged(QString)), + this, SIGNAL(unselectedLineStatusSet(QString))); + if(mCurrentLine->isAvailable()) { + mSession->stopTone(); + } + mCurrentLine->unselect(); + mCurrentLine = NULL; + + emit lineStatusSet(""); + emit actionSet(""); + emit bufferStatusSet(""); + emit talkingStopped(); + } +} + +PhoneLine * +PhoneLineManagerImpl::selectNextAvailableLine() +{ + isInitialized(); + + PhoneLine *selectedLine = getNextAvailableLine(); + + // If we found one available line. + if(selectedLine) { + unselect(); + select(selectedLine); + } + + return selectedLine; +} + + + +PhoneLine * +PhoneLineManagerImpl::getPhoneLine(unsigned int line) +{ + isInitialized(); + + if(mPhoneLines.size() <= line) { + throw std::runtime_error("Trying to get an invalid Line"); + } + + return mPhoneLines[line]; +} + +PhoneLine * +PhoneLineManagerImpl::getPhoneLine(const QString &callId) +{ + isInitialized(); + + PhoneLine *selectedLine = NULL; + + unsigned int i = 0; + while(i < mPhoneLines.size() && + !selectedLine) { + if(mPhoneLines[i]->getCallId() == callId) { + selectedLine = mPhoneLines[i]; + } + else { + i++; + } + } + + return selectedLine; +} + + +void +PhoneLineManagerImpl::sendKey(Qt::Key c) +{ + isInitialized(); + + PhoneLine *selectedLine = getCurrentLine(); + + // Only digits that select a line if there's + // no current line. + switch(c) { + case Qt::Key_F1: + case Qt::Key_F2: + case Qt::Key_F3: + case Qt::Key_F4: + case Qt::Key_F5: + case Qt::Key_F6: + selectLine(c - Qt::Key_F1); + break; + + default: + if (!selectedLine) { + selectedLine = selectNextAvailableLine(); + } + + if(selectedLine) { + if (c == Qt::Key_Enter || c == Qt::Key_Return) { + mLastNumber = selectedLine->getBuffer(); + } + selectedLine->sendKey(c); + } + } +} + + +void +PhoneLineManagerImpl::selectLine(const QString &callId, bool hardselect) +{ + isInitialized(); + + PhoneLine *selectedLine = NULL; + unsigned int line = 0; + while(!selectedLine && line < mPhoneLines.size()) { + if(mPhoneLines[line]->getCallId() == callId) { + selectedLine = mPhoneLines[line]; + } + else { + line++; + } + } + + if(selectedLine) { + selectLine(line, hardselect); + } + else { + DebugOutput::instance() << QObject::tr("PhoneLineManager: Tried to selected line with call ID (%1), " + "which appears to be invalid.\n").arg(callId); + } +} + +void +PhoneLineManagerImpl::unselectLine(unsigned int line) +{ + isInitialized(); + + PhoneLine *selectedLine = NULL; + // getting the wanted line; + { + if(mPhoneLines.size() > line) { + selectedLine = mPhoneLines[line]; + } + } + + if(selectedLine == mCurrentLine) { + unselect(); + } +} + +/** + * Warning: This function might 'cause a problem if + * we select 2 line in a very short time. + */ +void +PhoneLineManagerImpl::selectLine(unsigned int line, bool hardselect) +{ + isInitialized(); + + PhoneLine *selectedLine = NULL; + // getting the wanted line; + { + if(mPhoneLines.size() > line) { + selectedLine = mPhoneLines[line]; + } + } + + if(selectedLine != NULL) { + PhoneLine *oldLine = mCurrentLine; + + if(oldLine != selectedLine) { + select(selectedLine, hardselect); + } + } + else { + DebugOutput::instance() << QObject::tr("PhoneLineManager: Tried to selected line %1, " + "which appears to be invalid.\n").arg(line); + } +} + +void +PhoneLineManagerImpl::call(const QString &to) +{ + PhoneLine *current = getCurrentLine(); + if(current) { + current->call(to); + mLastNumber = to; + } +} + + +void +PhoneLineManagerImpl::call() +{ + PhoneLine *current = getCurrentLine(); + if(current) { + mLastNumber = current->getBuffer(); + current->call(); + } +} + +void +PhoneLineManagerImpl::makeNewCall(const QString& to) +{ + selectNextAvailableLine(); + call(to); +} + + +void +PhoneLineManagerImpl::transfer() +{ + if(mCurrentLine) { + mCurrentLine->transfer(); + } +} + + + +void +PhoneLineManagerImpl::hold() +{ + PhoneLine *selectedLine = mCurrentLine; + mCurrentLine = NULL; + + if(selectedLine) { + if(selectedLine->isAvailable()) { + mSession->stopTone(); + } + selectedLine->hold(); + } +} + +void +PhoneLineManagerImpl::redial() +{ + PhoneLine *phoneLine = selectNextAvailableLine(); + if(phoneLine && !mLastNumber.isEmpty()) { + phoneLine->call(mLastNumber); + } +} + +void +PhoneLineManagerImpl::hangup(bool sendrequest) +{ + PhoneLine *selectedLine = mCurrentLine; + mCurrentLine = NULL; + + if(selectedLine) { + if(selectedLine->isAvailable()) { + mSession->stopTone(); + } + selectedLine->hangup(sendrequest); + lineStatusSet(""); + } +} + +void +PhoneLineManagerImpl::mute(bool muting) +{ + if(muting) { + mute(); + } + else { + unmute(); + } +} + +void +PhoneLineManagerImpl::mute() +{ + isInitialized(); + + mSession->mute(); +} + +void +PhoneLineManagerImpl::setup() +{ + isInitialized(); + + mSession->configGetAll(); +} + +void +PhoneLineManagerImpl::unmute() +{ + isInitialized(); + + mSession->unmute(); +} + +void +PhoneLineManagerImpl::hangup(const QString &callId, bool sendrequest) +{ + PhoneLine *selectedLine = getPhoneLine(callId); + hangup(selectedLine, sendrequest); +} + +void +PhoneLineManagerImpl::hangup(unsigned int line, bool sendrequest) +{ + PhoneLine *selectedLine = getPhoneLine(line); + hangup(selectedLine, sendrequest); +} + +void +PhoneLineManagerImpl::hangup(PhoneLine *line, bool sendrequest) +{ + if(line) { + line->hangup(sendrequest); + if(mCurrentLine == line) { + unselect(); + } + } +} + +void +PhoneLineManagerImpl::clear() +{ + PhoneLine *selectedLine = mCurrentLine; + + if(selectedLine) { + selectedLine->clear(); + } +} + +void +PhoneLineManagerImpl::incomming(const QString &accountId, + const QString &callId, + const QString &peer) +{ + Call call(mSession->id(), accountId, callId, peer, true); + PhoneLine *line = addCall(call, QObject::tr("Incomming")); + if(line) { + line->setLineStatus(QObject::tr("Ringing (%1)...").arg(peer)); + } +} + +PhoneLine * +PhoneLineManagerImpl::addCall(const QString &accountId, + const QString &callId, + const QString &peer, + const QString &state) +{ + return addCall(Call(mSession->id(), accountId, callId, peer), state); +} + +PhoneLine * +PhoneLineManagerImpl::addCall(Call call, + const QString &state) +{ + PhoneLine *selectedLine = getNextAvailableLine(); + + if(selectedLine) { + selectedLine->incomming(call); + selectedLine->setLineStatus(state); + } + else { + DebugOutput::instance() << QObject::tr("PhoneLineManager: There's no available lines" + "here for the incomming call ID: %1.\n") + .arg(call.id()); + call.notAvailable(); + } + + return selectedLine; +} + +void +PhoneLineManagerImpl::updateVolume(int volume) +{ + mVolume = volume; + emit volumeUpdated((unsigned int)volume); +} + +void +PhoneLineManagerImpl::updateMicVolume(int volume) +{ + mMicVolume = volume; + emit micVolumeUpdated((unsigned int)volume); +} + +void +PhoneLineManagerImpl::setVolume(int volume) +{ + if(mVolume != volume) { + mSession->volume(volume); + updateVolume(volume); + } +} + +void +PhoneLineManagerImpl::setMicVolume(int volume) +{ + if(mMicVolume != volume) { + mSession->micVolume(volume); + updateMicVolume(volume); + } +} + +void +PhoneLineManagerImpl::incomingMessageText(const QString& message) +{ + QMessageBox messageBox; + messageBox.setText(message); + messageBox.exec(); +} + + diff --git a/src/gui/qt/PhoneLineManagerImpl.hpp b/src/gui/qt/PhoneLineManagerImpl.hpp new file mode 100644 index 0000000000..3d1b46eb52 --- /dev/null +++ b/src/gui/qt/PhoneLineManagerImpl.hpp @@ -0,0 +1,350 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Yan Morin <yan.morin@savoirfairelinux.com> + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __PHONELINEMANAGERIMPL_HPP__ +#define __PHONELINEMANAGERIMPL_HPP__ + +//#include <qt.h> +#include <qobject.h> +#include <qdatetime.h> +#include <utility> +#include <vector> + +class PhoneLine; + +#include "Account.hpp" +#include "Call.hpp" +#include "EventFactory.hpp" +#include "Session.hpp" + +/** + * This is the class that manages phone lines + */ +class PhoneLineManagerImpl : public QObject +{ + Q_OBJECT + +public: + PhoneLineManagerImpl(); + ~PhoneLineManagerImpl(); + + /** + * Will return the PhoneLine linked to the line + * number. + */ + PhoneLine *getPhoneLine(unsigned int line); + + /** + * Will return the PhoneLine with the call ID. + * If there's no PhoneLine of call ID, it will + * return NULL. + */ + PhoneLine *getPhoneLine(const QString &callId); + + PhoneLine *getCurrentLine(); + + void setNbLines(unsigned int line); + + bool isConnected() { return mIsConnected; } + +signals: + void unselected(unsigned int); + void selected(unsigned int); + void connected(); + void disconnected(); + void readyToSendStatus(); + void readyToHandleEvents(); + void handleEventsSent(); + void gotErrorOnGetEvents(QString); + void gotErrorOnCallStatus(QString); + void globalStatusSet(QString); + void bufferStatusSet(QString); + void actionSet(QString); + void unselectedLineStatusSet(QString); + void lineStatusSet(QString); + void talkingStarted(QTime); + void talkingStopped(); + + void stopped(); + void registered(); + + void volumeUpdated(int); + void micVolumeUpdated(int); + +public slots: + + void redial(); + void transfer(); + + void hasDisconnected(); + + void registerToServer(); + + /** + * You need to call this function once. It must be + * call before doing anything in this class. + */ + void initialize(const Session &session); + + /** + * This function will make the process to start. + * It will connect to the server, and start the + * event handling. + */ + void connect(); + + void sendKey(Qt::Key c); + + /** + * This function will put the current line + * on hold. If there's no current line, + * it will do nothing. + */ + void hold(); + + /** + * This function will hanp up the current line + * If there's no current line, it will do nothing. + */ + void hangup(bool sendrequest = true); + + /** + * This function will mute the microphone if muting + * is true, it will unmute otherwise. + */ + void mute(bool); + + /** + * This function will mute the microphone + */ + void mute(); + + /** + * This function will unmute the microphone + */ + void unmute(); + + void setup(); + + /** + * This function will hanp up the line number given + * argument. Be aware that the first line is 1, not + * zero. + */ + void hangup(unsigned int line, bool sendrequest = true); + + /** + * This function will hanp up the line with the + * following call ID. If there's no line with + * the call ID, it will do nothing. + */ + void hangup(const QString &callId, bool sendrequest = true); + + /** + * This function will hanp up the given line. If the + * line is NULL, nothing will be done. + */ + void hangup(PhoneLine *line, bool sendrequest = true); + + /** + * This function will make a call on the + * current line. If there's no selected + * line, it will choose the first available. + */ + void call(const QString &to); + + /** + * This function will add an incomming call + * on a phone line. + */ + void incomming(const QString &accountId, + const QString &callId, + const QString &peer); + + /** + * This function is used to add a call on a + * phone line. + */ + PhoneLine *addCall(Call call, + const QString &state); + PhoneLine *addCall(const QString &accountId, + const QString &callId, + const QString &peer, + const QString &state); + + /** + * This function will make a call on the + * current line. If there's no selected + * line. It will do nothing. It will call + * the destination contained in the + * PhoneLine buffer, if any. + */ + void call(); + + /** + * This function make select a new line and make a call + */ + void makeNewCall(const QString& to); + + /** + * This function will switch the lines. If the line + * is invalid, it just do nothing. + */ + void selectLine(unsigned int line, + bool hardselect = false); + + /** + * This function will switch the lines. If the line + * is invalid, it just do nothing. + */ + void unselectLine(unsigned int line); + + /** + * This function will switch the line to the line having + * the given call id. If the line is invalid, it just do + * nothing. + */ + void selectLine(const QString &callId, + bool hardselect = false); + + /** + * This function will clear the buffer of the active + * line. If there's no active line, it will do nothing. + */ + void clear(); + + /** + * This function will return the next available line. + * The line is locked, So you'll need to unlock it. + */ + PhoneLine *getNextAvailableLine(); + + /** + * This function will return the PhoneLine with the + * given id. If there's no such line, it will return + * NULL. The line is locked, So you'll need to unlock it. + */ + PhoneLine *getLine(unsigned int line); + + /** + * This function will return the PhoneLine with the + * given call id. If there's no such line, it will + * return NULL. The line is locked, So you'll need to + * unlock it. + */ + PhoneLine *getLine(const Call &call); + + /** + * This function will return the next available line. + * The line is NOT locked. + */ + PhoneLine *selectNextAvailableLine(); + + /** + * This function will send the getevents request + * to the server. + * + * NOTE: This function MUST be called AFTER getcallstatus's + * completion. + */ + void handleEvents(); + + /** + * This function will simply signal the volume change. + */ + void updateVolume(int volume); + + /** + * This function will send a request to sflphoned + * to change the volume to the given percentage. + */ + void setVolume(int volume); + + /** + * This function will simply signal the mic volume change. + */ + void updateMicVolume(int volume); + + /** + * This function will send a request to sflphoned + * to change the mic volume to the given percentage. + */ + void setMicVolume(int volume); + + /** + * This function will simply signal a incoming text message + */ + void incomingMessageText(const QString &message); + + void errorOnGetEvents(const QString &message) + {emit gotErrorOnGetEvents(message);} + + void errorOnCallStatus(const QString &message) + {emit gotErrorOnCallStatus(message);} + + void stop(); + + void finishStop() + {emit stopped();} + + void unselect(); + + private slots: + /** + * This will send all the command needed when a + * connection has just been established. + */ + void startSession(); + + /** + * This function is called when we are disconnected + * from the server. This will unselect all phone lines. + */ + void closeSession(); + + +private: + /** + * Check if the PhoneLineManager is initialized + * or return an std::logic_error exception + */ + void isInitialized(); + void select(PhoneLine *line, bool hardselect = false); + +private: + Session *mSession; + Account *mAccount; + + std::vector< PhoneLine * > mPhoneLines; + PhoneLine *mCurrentLine; + bool mIsInitialized; + + int mVolume; + int mMicVolume; + + bool mIsConnected; + bool mIsStopping; + + QString mLastNumber; +}; + + +#endif diff --git a/src/gui/qt/QjListBoxPixmap.cpp b/src/gui/qt/QjListBoxPixmap.cpp new file mode 100644 index 0000000000..ab57fd5e9b --- /dev/null +++ b/src/gui/qt/QjListBoxPixmap.cpp @@ -0,0 +1,159 @@ +/* + Copyright(C)2004 Johan Thelin + johan.thelin -at- digitalfanatics.org + + Visit: http://www.digitalfanatics.org/e8johan/projects/jseries/index.html + + This file is part of the JSeries. + + JSeries 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. + + JSeries 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. + + You should have received a copy of the GNU General Public License + along with JSeries; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <qpainter.h> +#include <qstyle.h> + +#include "QjListBoxPixmap.hpp" + +QjListBoxPixmap::QjListBoxPixmap( PixmapLocation location, const QPixmap &pixmap, const QString &text, QListBox *listbox ) : QListBoxItem( listbox ) +{ + m_location = location; + m_pixmap = pixmap; + setText( text ); +} + +QjListBoxPixmap::QjListBoxPixmap( PixmapLocation location, const QPixmap &pixmap, const QString &text, QListBox *listbox, QListBoxItem *after ) : QListBoxItem( listbox, after ) +{ + m_location = location; + m_pixmap = pixmap; + setText( text ); +} + +QjListBoxPixmap::PixmapLocation QjListBoxPixmap::location() const +{ + return m_location; +} + +const QPixmap *QjListBoxPixmap::pixmap() const +{ + return &m_pixmap; +} + +void QjListBoxPixmap::setPixmap( const QPixmap &pixmap ) +{ + m_pixmap = pixmap; + listBox()->repaint(); +} + +int QjListBoxPixmap::height( const QListBox *lb ) const +{ + switch( m_location ) + { + case Above: + case Under: + + return 6 + m_pixmap.height() + lb->fontMetrics().height(); + + case Left: + case Right: + + if( m_pixmap.height() > lb->fontMetrics().height() ) + return 4 + m_pixmap.height(); + else + return 4 + lb->fontMetrics().height(); + + default: + return 0; + } +} + +int QjListBoxPixmap::width( const QListBox *lb ) const +{ + int tw; + + switch( m_location ) + { + case Above: + case Under: + + tw = lb->fontMetrics().width( text() ); + + if( tw > m_pixmap.width() ) + return 4 + tw; + else + return 4 + m_pixmap.width(); + + case Left: + case Right: + + return 6 + m_pixmap.width() + lb->fontMetrics().width( text() ); + + default: + return 0; + } +} + +void QjListBoxPixmap::setLocation( PixmapLocation location ) +{ + if( m_location == location ) + return; + + m_location = location; + listBox()->repaint(); +} + +void QjListBoxPixmap::paint( QPainter *p ) +{ + if( !( listBox() && listBox()->viewport() == p->device() ) ) + return; + + QRect r( 0, 0, listBox()->width(), height( listBox() ) ); + + if( isSelected() ) + p->eraseRect( r ); + + int tw = listBox()->fontMetrics().width( text() ); + int th = listBox()->fontMetrics().height(); + int pw = m_pixmap.width(); + int ph = m_pixmap.height(); + int xo = (listBox()->width() - width( listBox() ))/2; + int tyo = listBox()->fontMetrics().ascent(); + + switch( m_location ) + { + case Above: + p->drawText( (listBox()->width()-tw)/2, ph+4+tyo, text() ); + p->drawPixmap( (listBox()->width()-pw)/2, 2, m_pixmap ); + + break; + case Under: + p->drawText( (listBox()->width()-tw)/2, 2+tyo, text() ); + p->drawPixmap( (listBox()->width()-pw)/2, 4+th, m_pixmap ); + + break; + case Left: + p->drawText( xo+2+pw, (height( listBox() )-th)/2+tyo, text() ); + p->drawPixmap( xo, (height( listBox() )-ph)/2, m_pixmap ); + + break; + case Right: + p->drawText( xo, (height( listBox() )-th)/2+tyo, text() ); + p->drawPixmap( xo+2+tw, (height( listBox() )-ph)/2, m_pixmap ); + + break; + } + + if( isCurrent() ) + listBox()->style().drawPrimitive( QStyle::PE_FocusRect, p, r, listBox()->colorGroup() ); +} diff --git a/src/gui/qt/QjListBoxPixmap.hpp b/src/gui/qt/QjListBoxPixmap.hpp new file mode 100644 index 0000000000..d8839e30f4 --- /dev/null +++ b/src/gui/qt/QjListBoxPixmap.hpp @@ -0,0 +1,73 @@ +/* + Copyright(C)2004 Johan Thelin + johan.thelin -at- digitalfanatics.org + + Visit: http://www.digitalfanatics.org/e8johan/projects/jseries/index.html + + This file is part of the JSeries. + + JSeries 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. + + JSeries 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. + + You should have received a copy of the GNU General Public License + along with JSeries; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef QjLISTBOXPIXMAP_H +#define QjLISTBOXPIXMAP_H + +#include <qlistbox.h> +#include <qstring.h> +#include <qpixmap.h> + +/** \brief The JPixmapItem is a listbox item showing a pixmap and a text. The location of the pixmap in relation to the text can be altered. + * + * \image html jpmi.png + * The location of the pixmap in relation to the text can be altered using the location and setLocation members. + */ +class QjListBoxPixmap : public QListBoxItem +{ +public: + /** Specifies the location of the pixmap in relation to the text. */ + enum PixmapLocation + { Above, /**< The pixmap is above the text. */ + Under, /**< The pixmap is under the text. */ + Left, /**< The pixmap is to the left of the text. */ + Right /**< The pixmap is to the right of the text. */ + }; + + /** Creates a JPixmapItem. */ + QjListBoxPixmap( PixmapLocation location, const QPixmap &pixmap, const QString &text, QListBox *listbox=0 ); + /** Creates a JPixmapItem at a certain position in the listbox. */ + QjListBoxPixmap( PixmapLocation location, const QPixmap &pixmap, const QString &text, QListBox *listbox, QListBoxItem *after ); + + /** Returns the pixmap location in relation to the text. */ + PixmapLocation location() const; + /** Sets the pixmap location in relation to the text. This does not generate a re-paint of the listbox. */ + void setLocation( PixmapLocation ); + + /** Returns the pixmap. */ + const QPixmap *pixmap() const; + /** Sets the pixmap. This does not generate a re-paint of the listbox. */ + void setPixmap( const QPixmap &pixmap ); + + int height( const QListBox *lb ) const; + int width( const QListBox *lb ) const; + +protected: + void paint( QPainter *p ); + +private: + QPixmap m_pixmap; + PixmapLocation m_location; +}; + +#endif // QjLISTBOXPIXMAP_H diff --git a/src/gui/qt/Request.cpp b/src/gui/qt/Request.cpp new file mode 100644 index 0000000000..9c0ed301f8 --- /dev/null +++ b/src/gui/qt/Request.cpp @@ -0,0 +1,243 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qobject.h> +#include <qstringlist.h> +#include <qurl.h> + +#include "globals.h" +#include "DebugOutput.hpp" +#include "CallManager.hpp" +#include "Request.hpp" +#include "Requester.hpp" +#include "Url.hpp" + +Request::Request(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : mSequenceId(sequenceId) + , mCommand(command) + , mArgs(args) +{} + +std::list< QString > +Request::parseArgs(const QString &message) +{ + QStringList list(QStringList::split(" ", message)); + std::list< QString > args; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString qs(*it); + Url::decode(qs); + args.push_back(qs); + } + + return args; +} + +void +Request::onError(const QString &code, const QString &message) +{ + DebugOutput::instance() << QObject::tr("Received an error:\n " + "Code: %1\n " + "SequenceID: %2\n Message: %3\n") + .arg(code) + .arg(mSequenceId) + .arg(message); + + emit error(message, code); +} + +void +Request::onEntry(const QString &code, const QString &message) +{ + DebugOutput::instance() << QObject::tr("Received a temp info:\n " + "Code: %1\n " + "SequenceID: %2\n " + "Message: %3\n") + .arg(code) + .arg(mSequenceId) + .arg(message); + + emit entry(message, code); + + // This is bad code, I know. I need to find a better way. + std::list< QString > args = parseArgs(message); + QString arg1, arg2, arg3, arg4, arg5; + if(args.size() >= 1) { + arg1 = *args.begin(); + args.pop_front(); + } + if(args.size() >= 1) { + arg2 = *args.begin(); + args.pop_front(); + } + if(args.size() >= 1) { + arg3 = *args.begin(); + args.pop_front(); + } + if(args.size() >= 1) { + arg4 = *args.begin(); + args.pop_front(); + } + if(args.size() >= 1) { + arg5 = *args.begin(); + args.pop_front(); + } + emit parsedEntry(arg1, arg2, arg3, arg4, arg5); +} + +void +Request::onSuccess(const QString &code, const QString &message) +{ + DebugOutput::instance() << QObject::tr("Received a success info:\n " + "Code: %1\n " + "SequenceID: %2\n " + "Message: %3\n") + .arg(code) + .arg(mSequenceId) + .arg(message); + + emit success(message, code); +} + +QString +Request::toString() +{ + QString output = mCommand + " " + mSequenceId; + for(std::list< QString >::const_iterator pos = mArgs.begin(); + pos != mArgs.end(); + pos++) { + QString ostring(*pos); + QUrl::encode(ostring); + output += " " + ostring; + } + output += "\n"; + + return output; +} + + +CallRelatedRequest::CallRelatedRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : Request(sequenceId, command, args) +{ + if(args.begin() != args.end()) { + mCallId = *args.begin(); + } +} + +void +CallRelatedRequest::onError(const QString &code, const QString &message) +{ + if(CallManager::instance().exist(mCallId)) { + onError(CallManager::instance().getCall(mCallId), + code, + message); + } + else { + DebugOutput::instance() << QObject::tr("CallRelatedRequest: Trying to retreive an unregistred call (%1)\n").arg(mCallId); + } +} + +void +CallRelatedRequest::onError(Call, const QString &, const QString &) +{} + +void +CallRelatedRequest::onEntry(const QString &code, const QString &message) +{ + if(CallManager::instance().exist(mCallId)) { + onEntry(CallManager::instance().getCall(mCallId), + code, + message); + } + else { + DebugOutput::instance() << QObject::tr("CallRelatedRequest: Trying to retreive an unregistred call (%1)\n").arg(mCallId); + } +} + +void +CallRelatedRequest::onEntry(Call, const QString &, const QString &) +{} + +void +CallRelatedRequest::onSuccess(const QString &code, const QString &message) +{ + if(CallManager::instance().exist(mCallId)) { + onSuccess(CallManager::instance().getCall(mCallId), + code, + message); + } + else { + DebugOutput::instance() << QObject::tr("CallRelatedRequest: Trying to retreive an unregistred call (%1)\n").arg(mCallId); + } +} + +void +CallRelatedRequest::onSuccess(Call, const QString &, const QString &) +{} + +AccountRequest::AccountRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : Request(sequenceId, command, args) + , mAccountId(*args.begin()) +{} + +void +AccountRequest::onError(const QString &code, const QString &message) +{ + onError(Account(Requester::instance().getSessionIdFromSequenceId(getSequenceId()), + mAccountId), + code, + message); +} + +void +AccountRequest::onError(Account, const QString &, const QString &) +{} + +void +AccountRequest::onEntry(const QString &code, const QString &message) +{ + onEntry(Account(Requester::instance().getSessionIdFromSequenceId(getSequenceId()), + mAccountId), + code, + message); +} + +void +AccountRequest::onEntry(Account, const QString &, const QString &) +{} + +void +AccountRequest::onSuccess(const QString &code, const QString &message) +{ + onSuccess(Account(Requester::instance().getSessionIdFromSequenceId(getSequenceId()), + mAccountId), + code, + message); +} + +void +AccountRequest::onSuccess(Account, const QString &, const QString &) +{} + diff --git a/src/gui/qt/Request.hpp b/src/gui/qt/Request.hpp new file mode 100644 index 0000000000..63c2cdb4ca --- /dev/null +++ b/src/gui/qt/Request.hpp @@ -0,0 +1,245 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef SFLPHONEGUI_REQUEST_H +#define SFLPHONEGUI_REQUEST_H + +#include <list> +#include <qobject.h> +#include <qstring.h> + + +#include "Account.hpp" +#include "Call.hpp" + +class Request : public QObject +{ + Q_OBJECT + +signals: + /** + * Be aware that the first string is the message, + * and the second is the code. This is done that + * way because usually the message is more important + * than the code. + */ + void error(QString, QString); + void success(QString, QString); + void entry(QString, QString); + void parsedEntry(QString, QString, QString, QString, QString); + +public: + Request(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + virtual ~Request(){} + + /** + * This function will parse the message and will cut the message + * in many arguments. + */ + static std::list< QString > parseArgs(const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the request didn't successfully + * ended. + */ + virtual void onError(const QString &code, const QString &message); + + /** + * This function will be called when the request + * receive an answer, but there's other answers to come. + */ + virtual void onEntry(const QString &code, const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the request successfully + * ended. + */ + virtual void onSuccess(const QString &code, const QString &message); + + /** + * This function will translate the function into a string. + * This is used for sending the request through a text channel. + */ + QString toString(); + + /** + * Return the sequence ID. + */ + QString getSequenceId() + {return mSequenceId;} + + /** + * Return the command. + */ + QString getCommand() + {return mCommand;} + + /** + * Return the args. + */ + std::list< QString > getArgs() + {return mArgs;} + + + private: + const QString mSequenceId; + const QString mCommand; + const std::list< QString > mArgs; +}; + +class CallRelatedRequest : public Request +{ + public: + CallRelatedRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + + /** + * This function will be called when the request + * receive its answer, if the request didn't successfully + * ended. + */ + virtual void onError(Call call, + const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive an answer, but there's other answers to come. + */ + virtual void onEntry(Call call, + const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the request successfully + * ended. + */ + virtual void onSuccess(Call call, + const QString &code, + const QString &message); + + private: + /** + * This function will be called when the request + * receive its answer, if the request didn't successfully + * ended. This function will call the onError, but with + * the call linked to this request. + */ + virtual void onError(const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the there's other answer to + * come. This function will call the onEntry, but with + * the call linked to this request. + */ + virtual void onEntry(const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the request successfully + * ended. This function will call the onSuccess function, + * but with the call linked to this request. + */ + virtual void onSuccess(const QString &code, + const QString &message); + + + private: + QString mCallId; +}; + +class AccountRequest : public Request +{ + public: + AccountRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + /** + * This function will be called when the request + * receive its answer, if the request didn't successfully + * ended. + */ + virtual void onError(Account account, + const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive an answer, but there's other answers to come. + */ + virtual void onEntry(Account account, + const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the request successfully + * ended. + */ + virtual void onSuccess(Account account, + const QString &code, + const QString &message); + + private: + /** + * This function will be called when the request + * receive its answer, if the request didn't successfully + * ended. This function will call the onError, but with + * the account linked to this request. + */ + virtual void onError(const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the there's other answer to + * come. This function will call the onEntry, but with + * the account linked to this request. + */ + virtual void onEntry(const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the request successfully + * ended. This function will call the onSuccess function, + * but with the account linked to this request. + */ + virtual void onSuccess(const QString &code, + const QString &message); + + + private: + const QString mAccountId; +}; + +#endif diff --git a/src/gui/qt/Requester.hpp b/src/gui/qt/Requester.hpp new file mode 100644 index 0000000000..2d6e4b20cd --- /dev/null +++ b/src/gui/qt/Requester.hpp @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author : Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef SFLPHONEGUI_REQUESTER_H +#define SFLPHONEGUI_REQUESTER_H + +#include "utilspp/Singleton.hpp" +#include "RequesterImpl.hpp" + +typedef utilspp::SingletonHolder< RequesterImpl > Requester; + +#endif + diff --git a/src/gui/qt/RequesterImpl.cpp b/src/gui/qt/RequesterImpl.cpp new file mode 100644 index 0000000000..4220539902 --- /dev/null +++ b/src/gui/qt/RequesterImpl.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qtextstream.h> +#include <iostream> +#include <stdexcept> +#include <sstream> + +#include "globals.h" +#include "DebugOutput.hpp" +#include "RequesterImpl.hpp" +#include "SessionIO.hpp" + +RequesterImpl::RequesterImpl() + : mCallIdCount(0) + , mSessionIdCount(0) + , mSequenceIdCount(0) +{} + +SessionIO * +RequesterImpl::getSessionIO(const QString &sessionId) +{ + std::map< QString, SessionIO * >::iterator pos = mSessions.find(sessionId); + if(pos == mSessions.end()) { + throw std::runtime_error("The session is not valid."); + } + + return (*pos).second; +} + +Request * +RequesterImpl::send(const QString &sessionId, + const QString &command, + const std::list< QString > &args) +{ + // We retreive the internal of a session. + SessionIO *session = getSessionIO(sessionId); + + // We ask the factory to create the request. + QString sequenceId = generateSequenceId(); + Request *request = mRequestFactory.create(command, sequenceId, args); + + registerRequest(sessionId, sequenceId, request); + session->send(request->toString()); + + return request; +} + +void +RequesterImpl::registerRequest(const QString &sessionId, + const QString &sequenceId, + Request *request) +{ + if(mRequests.find(sequenceId) != mRequests.end()) { + throw std::logic_error("Registering an already know sequence ID"); + } + + mRequests.insert(std::make_pair(sequenceId, request)); + mSequenceToSession.insert(std::make_pair(sequenceId, sessionId)); +} + +Request * +RequesterImpl::getRequest(const QString &sequenceId) +{ + Request *r = NULL; + + std::map< QString, Request * >::iterator pos = mRequests.find(sequenceId); + if(pos == mRequests.end()) { + r = pos->second; + } + + return r; +} + +void +RequesterImpl::registerSession(const QString &id, + SessionIO *s) +{ + if(mSessions.find(id) != mSessions.end()) { + throw std::logic_error("Registering an already know Session ID"); + } + + mSessions.insert(std::make_pair(id, s)); +} + +void +RequesterImpl::connect(const QString &id) +{ + std::map< QString, SessionIO * >::iterator pos = mSessions.find(id); + if(pos == mSessions.end()) { + throw std::logic_error("Trying to connect an unknown session."); + } + + pos->second->connect(); +} + + +int +RequesterImpl::getCodeCategory(const QString &code) +{ + return code.toInt() / 100; +} + +void +RequesterImpl::receiveAnswer(const QString &answer) +{ + QString a(answer); + QString code; + QString seq; + QString message; + + QTextStream s(&a, IO_ReadOnly); + s >> code >> seq; + message = s.readLine(); + message.remove(0, 1); + receiveAnswer(code, seq, message); +} + + +void +RequesterImpl::receiveAnswer(const QString &code, + const QString &sequence, + const QString &message) +{ + int c = getCodeCategory(code); + + std::map< QString, Request * >::iterator pos; + pos = mRequests.find(sequence); + if(pos == mRequests.end()) { + DebugOutput::instance() << QObject::tr("Requester: We received an answer " + "with an unknown sequence (%1).\n") + .arg(sequence); + return; + } + + if(c <= 1) { + //Other answers will come for this request. + pos->second->onEntry(code, message); + } + else{ + //This is the final answer of this request. + if(c == 2) { + pos->second->onSuccess(code, message); + } + else { + pos->second->onError(code, message); + } + delete pos->second; + mRequests.erase(pos); + } +} + +QString +RequesterImpl::generateCallId() +{ + return QString("cCallID:%1").arg(mCallIdCount++); +} + +QString +RequesterImpl::generateSessionId() +{ + return QString("cSessionID:%1").arg(mSequenceIdCount++); +} + +QString +RequesterImpl::generateSequenceId() +{ + return QString("cSequenceID:%1").arg(mSequenceIdCount++); +} + +void +RequesterImpl::inputIsDown(const QString &sessionId) +{ + std::map< QString, SessionIO * >::iterator pos; + pos = mSessions.find(sessionId); + if(pos == mSessions.end()) { + // we will not thow an exception, but this is + // a logic error + DebugOutput::instance() << QObject::tr("Requester: SessionIO input for session %1 is down, " + "but we don't have that session.\n") + .arg(sessionId); + } +} diff --git a/src/gui/qt/RequesterImpl.hpp b/src/gui/qt/RequesterImpl.hpp new file mode 100644 index 0000000000..1ebfcff3b6 --- /dev/null +++ b/src/gui/qt/RequesterImpl.hpp @@ -0,0 +1,150 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef SFLPHONEGUI_REQUESTERIMPL_H +#define SFLPHONEGUI_REQUESTERIMPL_H + +#include <list> + +#include "Request.hpp" +#include "ObjectFactory.hpp" + +class AnswerReceiver; +class Call; +class SessionIO; + +class RequesterImpl +{ + public: + RequesterImpl(); + + /** + * Will send the command to the sflphone's server. + * This command is non-blocking. The command linked + * to this command will be executed. + */ + Request *send(const QString &sessionId, + const QString &command, + const std::list< QString > &args); + + void receiveAnswer(const QString &answer); + void receiveAnswer(const QString &code, + const QString &sequence, + const QString &message); + + + static int getCodeCategory(const QString &code); + + /** + * Generate a unique call ID. + */ + QString generateCallId(); + + /** + * Generate a unique session ID. + */ + QString generateSessionId(); + + /** + * Generate a unique sequence ID. + */ + QString generateSequenceId(); + + /** + * Register the string to return a Actual type. + */ + template< typename Actual > + void registerObject(const QString &name); + + /** + * Register the default request to be created if + * the command isn't registered. + */ + template< typename Actual > + void registerDefaultObject(); + + + QString getSessionIdFromSequenceId(const QString &sequence) + {return mSequenceToSession[sequence];} + + /** + * Register the session. + */ + void registerSession(const QString &id, SessionIO *io); + + /** + * Will ask the session IO with id to connect. + */ + void connect(const QString &id); + + /** + * This function is used to notify that the SessionIO + * input of a session is down. It means that we no longer + * can receive answers. + * + * Note: Only SessionIO related classes should call this function. + */ + void inputIsDown(const QString &sessionId); + + /** + * This function is used to notify that the SessionIO + * output of a session is down. It means that we no longer + * can send requests. + * + * Note: Only SessionIO related classes should call this function. + */ + void outputIsDown(const QString &sessionId); + + private: + + /** + * Return the SessionIO instance related to + * the session ID. + */ + SessionIO *getSessionIO(const QString &sessionId); + + /** + * Register the string to return a Actual type. + */ + void registerRequest(const QString &sessionId, + const QString &sequenceId, + Request *request); + + Request *getRequest(const QString &sessionId); + + + private: + ObjectFactory< Request > mRequestFactory; + std::map< QString, SessionIO * > mSessions; + std::map< QString, Request * > mRequests; + std::map< QString, QString > mSequenceToSession; + + + /** + * This is the integer used to generate the call IDs. + */ + unsigned long mCallIdCount; + unsigned long mSessionIdCount; + unsigned long mSequenceIdCount; +}; + +#include "RequesterImpl.inl" + +#endif diff --git a/src/gui/qt/RequesterImpl.inl b/src/gui/qt/RequesterImpl.inl new file mode 100644 index 0000000000..ed09e3a187 --- /dev/null +++ b/src/gui/qt/RequesterImpl.inl @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef SFLPHONEGUI_REQUESTERIMPL_INL +#define SFLPHONEGUI_REQUESTERIMPL_INL + +template< typename Actual > +void +RequesterImpl::registerObject(const QString &name) +{ + mRequestFactory.registerObject< Actual >(name); +} + +template< typename Actual > +void +RequesterImpl::registerDefaultObject() +{ + mRequestFactory.registerDefaultObject< Actual >(); +} + + +#endif diff --git a/src/gui/qt/SFLCallStatus.hpp b/src/gui/qt/SFLCallStatus.hpp new file mode 100644 index 0000000000..e322da49f9 --- /dev/null +++ b/src/gui/qt/SFLCallStatus.hpp @@ -0,0 +1,35 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SFLCALLSTATUS_HPP__ +#define __SFLCALLSTATUS_HPP__ + +#include "CallStatus.hpp" + + +typedef CallStatus TryingStatus; +typedef CallStatus RingingStatus; +typedef CallStatus HoldStatus; +typedef CallStatus EstablishedStatus; +typedef CallStatus BusyStatus; +typedef CallStatus CongestionStatus; +typedef CallStatus WrongNumberStatus; + +#endif diff --git a/src/gui/qt/SFLEvents.cpp b/src/gui/qt/SFLEvents.cpp new file mode 100644 index 0000000000..ccfd0bb81a --- /dev/null +++ b/src/gui/qt/SFLEvents.cpp @@ -0,0 +1,144 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "globals.h" + +#include "PhoneLineManager.hpp" +#include "SFLEvents.hpp" + +DefaultEvent::DefaultEvent(const QString &code, + const std::list< QString > &args) + : Event(code, args) +{ +} + +void +DefaultEvent::execute() +{ + DebugOutput::instance() << QObject::tr("DefaultEvent: We don't handle: %1\n").arg(toString()); +} + + +HangupEvent::HangupEvent(const QString &code, + const std::list< QString > &args) + : CallRelatedEvent(code, args) +{} + +void +HangupEvent::execute() +{ + QString id = getCallId(); + if(id.length() > 0) { + DebugOutput::instance() << QObject::tr("Hangup Event received for call ID: %1.\n") + .arg(id); + PhoneLineManager::instance().hangup(id, false); + } + else { + DebugOutput::instance() << QObject::tr("Hangup Event invalid (missing call ID): %1\n") + .arg(toString()); + } +} + +IncommingEvent::IncommingEvent(const QString &code, + const std::list< QString > &args) + : CallRelatedEvent(code, args) +{ + std::list< QString > l = getUnusedArgs(); + if(l.size() >= 2) { + mAccountId = *l.begin(); + l.pop_front(); + mOrigin = *l.begin(); + l.pop_front(); + setUnusedArgs(l); + } +} + +void +IncommingEvent::execute() +{ + QString id = getCallId(); + if(id.length() > 0) { + DebugOutput::instance() << QObject::tr("Incomming Event received for call ID: %1.\n") + .arg(id); + PhoneLineManager::instance().incomming(mAccountId, getCallId(), mOrigin); + } + else { + DebugOutput::instance() << QObject::tr("Incomming Event invalid: %1\n") + .arg(toString()); + } +} + +VolumeEvent::VolumeEvent(const QString &code, + const std::list< QString > &args) + : Event(code, args) +{ + std::list< QString > l = getUnusedArgs(); + if(l.size() >= 1) { + mVolume = l.begin()->toUInt(); + l.pop_front(); + setUnusedArgs(l); + } +} + +void +VolumeEvent::execute() +{ + PhoneLineManager::instance().updateVolume(mVolume); +} + +MicVolumeEvent::MicVolumeEvent(const QString &code, + const std::list< QString > &args) + : VolumeEvent(code, args) +{} + +void +MicVolumeEvent::execute() +{ + PhoneLineManager::instance().updateMicVolume(mVolume); +} + +MessageTextEvent::MessageTextEvent(const QString &code, + const std::list< QString > &args) + : Event(code, args) +{ + std::list< QString > l = getUnusedArgs(); + if(l.size() >= 1) { + mMessage = *l.begin(); + l.pop_front(); + setUnusedArgs(l); + } +} + +void +MessageTextEvent::execute() +{ + PhoneLineManager::instance().incomingMessageText(mMessage); +} + +LoadSetupEvent::LoadSetupEvent(const QString &code, + const std::list< QString > &args) + : Event(code, args) +{} + +void +LoadSetupEvent::execute() +{ + PhoneLineManager::instance().setup(); +} diff --git a/src/gui/qt/SFLEvents.hpp b/src/gui/qt/SFLEvents.hpp new file mode 100644 index 0000000000..ee5cb0c05c --- /dev/null +++ b/src/gui/qt/SFLEvents.hpp @@ -0,0 +1,102 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SFLEVENTS_HPP__ +#define __SFLEVENTS_HPP__ + +#include <list> +#include "Event.hpp" + +class DefaultEvent : public Event +{ +public: + DefaultEvent(const QString &code, + const std::list< QString > &args); + + virtual void execute(); +}; + +class HangupEvent : public CallRelatedEvent +{ +public: + HangupEvent(const QString &code, + const std::list< QString > &args); + + virtual void execute(); +}; + +class IncommingEvent : public CallRelatedEvent +{ +public: + IncommingEvent(const QString &code, + const std::list< QString > &args); + + virtual void execute(); + +private: + QString mAccountId; + QString mOrigin; +}; + + +class VolumeEvent : public Event +{ +public: + VolumeEvent(const QString &code, + const std::list< QString > &args); + + virtual void execute(); + +protected: + unsigned int mVolume; +}; + +class MicVolumeEvent : public VolumeEvent +{ +public: + MicVolumeEvent(const QString &code, + const std::list< QString > &args); + + virtual void execute(); + +}; + +class MessageTextEvent : public Event +{ +public: + MessageTextEvent(const QString &code, + const std::list< QString > &args); + + virtual void execute(); + +protected: + QString mMessage; +}; + +class LoadSetupEvent : public Event +{ +public: + LoadSetupEvent(const QString &code, + const std::list< QString > &args); + + virtual void execute(); +}; + +#endif diff --git a/src/gui/qt/SFLLcd.cpp b/src/gui/qt/SFLLcd.cpp new file mode 100644 index 0000000000..4051cf666e --- /dev/null +++ b/src/gui/qt/SFLLcd.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Yan Morin <yan.morin@savoirfairelinux.com> + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qdatetime.h> +#include <qpainter.h> +#include <qevent.h> +#include <qdragobject.h> + +#include "globals.h" +#include "JPushButton.hpp" +#include "SFLLcd.hpp" +#include "TransparentWidget.hpp" +// should send a signal... not include this +#include "PhoneLineManager.hpp" + +#include "DebugOutput.hpp" // to remove after testing + + +#define FONT_FAMILY "Courier" +// Others fixed font support "Monospace", "Fixed", "MiscFixed" +#define FONT_SIZE 10 + +#define SCREEN "screen_main.png" +#define OVERSCREEN "overscreen.png" + +SFLLcd::SFLLcd(QWidget *parent) + : QLabel(parent, "SFLLcd", Qt::WNoAutoErase) + , mScreen(TransparentWidget::retreive(SCREEN)) + , mOverscreen(TransparentWidget::retreive(OVERSCREEN)) + , mGlobalStatusPos(-1) + , mUnselectedLineStatusPos(-1) + , mLineStatusPos(-1) + , mBufferStatusPos(-1) + , mActionPos(-1) + , mIsTimed(false) + , mFont(FONT_FAMILY, FONT_SIZE) +{ + resize(mScreen.size()); + move(22,44); + + mUnselectedLineTimer = new QTimer(this); + QObject::connect(mUnselectedLineTimer, SIGNAL(timeout()), + this, SLOT(updateGlobalText())); + + mTimer = new QTimer(this); + QObject::connect(mTimer, SIGNAL(timeout()), + this, SLOT(updateText())); + QObject::connect(mTimer, SIGNAL(timeout()), + this, SLOT(update())); + mTimer->start(100); + + setAcceptDrops(TRUE); +} + +void +SFLLcd::updateText() +{ + if(mGlobalStatusPos >= 0) { + mGlobalStatusPos++; + } + + if(mLineStatusPos >= 0) { + mLineStatusPos++; + } + + if(mBufferStatusPos >= 0) { + mBufferStatusPos++; + } + + if(mActionPos >= 0) { + mActionPos++; + } +} + +void +SFLLcd::updateGlobalText() +{ + mUnselectedLineStatus = ""; +} + +void +SFLLcd::setLineTimer(QTime time) +{ + mIsTimed = true; + mTime = time; +} + +void +SFLLcd::clearLineTimer() +{ + mIsTimed = false; +} + +void +SFLLcd::setGlobalStatus(QString global) +{ + if(textIsTooBig(global)) { + mGlobalStatusPos = 0; + } + else { + mGlobalStatusPos = -1; + } + mGlobalStatus = global; +} + +void +SFLLcd::setBufferStatus(QString buffer) +{ + if(textIsTooBig(buffer)) { + mBufferStatusPos = 0; + } + else { + mBufferStatusPos = -1; + } + mBufferStatus = buffer; +} + +void +SFLLcd::setLineStatus(QString line) +{ + if(textIsTooBig(line)) { + mLineStatusPos = 0; + } + else { + mLineStatusPos = -1; + } + mLineStatus = line; +} + +void +SFLLcd::setUnselectedLineStatus(QString line) +{ + if(textIsTooBig(line)) { + mUnselectedLineStatusPos = 0; + } + else { + mUnselectedLineStatusPos = -1; + } + mUnselectedLineStatus = line; + mUnselectedLineTimer->start(3000, true); +} + +void +SFLLcd::setAction(QString line) +{ + if(textIsTooBig(line)) { + mActionPos = 0; + } + else { + mActionPos = -1; + } + mAction = line; +} + +QString +SFLLcd::getTimeStatus() +{ + if(mIsTimed) { + int seconds = mTime.elapsed() / 1000 ; + return QTime(seconds / 60 / 60, seconds / 60, seconds % 60).toString("hh:mm:ss"); + } + else { + QTime t(QTime::currentTime()); + QString s; + if(t.second() % 2) { + s = t.toString("hh:mm"); + } + else { + s = t.toString("hh mm"); + } + + return s; + } +} + +void +SFLLcd::paintEvent(QPaintEvent *event) +{ + static QPixmap pixmap(size()); + + QRect rect = event->rect(); + QSize newSize = rect.size().expandedTo(pixmap.size()); + pixmap.resize(newSize); + pixmap.fill(this, rect.topLeft()); + QPainter p(&pixmap, this); + + // Painter settings + QFontMetrics fm(mFont); + + int *globalStatusPos; + QString globalStatus; + if(mUnselectedLineStatus.length() > 0) { + globalStatus = mUnselectedLineStatus; + globalStatusPos = &mUnselectedLineStatusPos; + } + else { + globalStatus = mGlobalStatus; + globalStatusPos = &mGlobalStatusPos; + } + + int margin = 2; + p.setFont(mFont); + p.drawPixmap(0,0, mScreen); + p.drawText(QPoint(margin, fm.height()), + extractVisibleText(globalStatus, *globalStatusPos)); + p.drawText(QPoint(margin, 2*fm.height()), + extractVisibleText(mLineStatus, mLineStatusPos)); + p.drawText(QPoint(margin, 3*fm.height()), + extractVisibleText(mAction, mActionPos)); + p.drawText(QPoint(margin, 4*fm.height()), + extractVisibleText(mBufferStatus, mBufferStatusPos)); + + p.drawText(QPoint(margin, mScreen.size().height() - margin), getTimeStatus()); + p.drawPixmap(0,0, mOverscreen); + p.end(); + + bitBlt(this, event->rect().topLeft(), &pixmap); +} + +bool +SFLLcd::textIsTooBig(const QString &text) +{ + QFontMetrics fm(mFont); + + int screenWidth = mScreen.width() - 4; + int textWidth = fm.boundingRect(text).width(); + + if(textWidth > screenWidth) { + return true; + } + else { + return false; + } +} + +QString +SFLLcd::extractVisibleText(const QString &text, int &pos) +{ + QFontMetrics fm(mFont); + QString tmp(text); + + int nbCharBetween = 8; + + if(pos > 0 && ((unsigned int)pos >= tmp.length() + nbCharBetween)) { + pos = 0; + } + + // Chop the text until it's not too big + if(textIsTooBig(tmp)) { + // We add automatiquely the space the the text again at + // the end. + tmp += QString().fill(QChar(' '), nbCharBetween); + tmp += text; + + if(pos == -1) { + pos = 0; + } + + tmp.remove(0, pos); + while(textIsTooBig(tmp)) { + tmp.remove(tmp.length() - 1, 1); + } + } + + return tmp; +} + +/** + * Drag and drop handler : accept text drag + */ +void +SFLLcd::dragEnterEvent(QDragEnterEvent* event) +{ + event->accept( + QTextDrag::canDecode(event) + ); +} + +/** + * Drag and drop handler : make a call with text + */ +void +SFLLcd::dropEvent(QDropEvent* event) +{ + QString text; + + if ( QTextDrag::decode(event, text) && !text.isEmpty() ) { + PhoneLineManager::instance().makeNewCall(text); + } +} + +void +SFLLcd::mousePressEvent( QMouseEvent *e) +{ + if (e && e->button() == Qt::MidButton) { + emit midClicked(); + } +} diff --git a/src/gui/qt/SFLLcd.hpp b/src/gui/qt/SFLLcd.hpp new file mode 100644 index 0000000000..878e426c42 --- /dev/null +++ b/src/gui/qt/SFLLcd.hpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Yan Morin <yan.morin@savoirfairelinux.com> + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SFLLCD_HPP__ +#define __SFLLCD_HPP__ + +#include <qlabel.h> +#include <qobject.h> +#include <qpixmap.h> +#include <qdatetime.h> +#include <qtimer.h> + +class SFLLcd : public QLabel +{ + Q_OBJECT + +public: + SFLLcd(QWidget *parent = NULL); + + bool textIsTooBig(const QString &text); + +protected: + virtual void mousePressEvent( QMouseEvent * ); + +signals: + void midClicked(); + +public slots: + virtual void paintEvent(QPaintEvent *event); + QString getTimeStatus(); + + void setGlobalStatus(QString global); + void setUnselectedLineStatus(QString line); + void setLineStatus(QString line); + void setAction(QString line); + void setBufferStatus(QString line); + void setLineTimer(QTime time); + void clearLineTimer(); + + void updateText(); + void updateGlobalText(); + QString extractVisibleText(const QString &text, int &pos); + +private: + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); + + QPixmap mScreen; + QPixmap mOverscreen; + + QString mGlobalStatus; + QString mUnselectedLineStatus; + QString mLineStatus; + QString mBufferStatus; + QString mAction; + int mGlobalStatusPos; + int mUnselectedLineStatusPos; + int mLineStatusPos; + int mBufferStatusPos; + int mActionPos; + + bool mIsTimed; + QTime mTime; + QTimer *mTimer; + QTimer *mUnselectedLineTimer; + + QFont mFont; +}; + +#endif diff --git a/src/gui/qt/SFLPhoneApp.cpp b/src/gui/qt/SFLPhoneApp.cpp new file mode 100644 index 0000000000..f5ad6e3176 --- /dev/null +++ b/src/gui/qt/SFLPhoneApp.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Yan Morin <yan.morin@savoirfairelinux.com> + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "globals.h" + +#include "taxidermy/Hunter.hpp" + +#include "ConfigurationManager.hpp" +#include "Launcher.hpp" +#include "NumericKeypad.hpp" +#include "PhoneLine.hpp" +#include "PhoneLineButton.hpp" +#include "Requester.hpp" +#include "Session.hpp" +#include "SessionIOFactory.hpp" +#include "SFLLcd.hpp" +#include "SFLPhoneApp.hpp" +#include "SFLPhoneWindow.hpp" +#include "SFLRequest.hpp" +#include "SkinManager.hpp" +#include "TCPSessionIOCreator.hpp" +#include "VolumeControl.hpp" +#include <qclipboard.h> // paste + +SFLPhoneApp::SFLPhoneApp(int argc, char **argv) + : QApplication(argc, argv) + , mLauncher(new Launcher()) +{ + SessionIOFactory::instance().setCreator(new TCPSessionIOCreator(QString("localhost"), 3999)); + + Session session; + + ConfigurationManager::instance().setSession(session); + + PhoneLineManager::instance().initialize(session); + PhoneLineManager::instance().setNbLines(NB_PHONELINES); + Requester::instance().registerDefaultObject< Request >(); + Requester::instance().registerObject< Request >(QString("playtone")); + Requester::instance().registerObject< Request >(QString("stoptone")); + Requester::instance().registerObject< Request >(QString("playdtmf")); + + Requester::instance().registerObject< ConfigGetAllRequest >(QString("configgetall")); + Requester::instance().registerObject< ConfigSaveRequest >(QString("configsave")); + Requester::instance().registerObject< StopRequest >(QString("stop")); + + + Requester::instance().registerObject< EventRequest >(QString("getevents")); + Requester::instance().registerObject< CallStatusRequest >(QString("getcallstatus")); + Requester::instance().registerObject< PermanentRequest >(QString("answer")); + Requester::instance().registerObject< PermanentRequest >(QString("notavailable")); + Requester::instance().registerObject< PermanentRequest >(QString("refuse")); + Requester::instance().registerObject< PermanentRequest >(QString("hangup")); + Requester::instance().registerObject< TemporaryRequest >(QString("unmute")); + Requester::instance().registerObject< TemporaryRequest >(QString("hold")); + Requester::instance().registerObject< TemporaryRequest >(QString("unhold")); + Requester::instance().registerObject< TemporaryRequest >(QString("senddtmf")); + Requester::instance().registerObject< Request >(QString("setspkrvolume")); + Requester::instance().registerObject< Request >(QString("setmicvolume")); + Requester::instance().registerObject< Request >(QString("mute")); + + mKeypad = new NumericKeypad(); +} + +SFLPhoneApp::~SFLPhoneApp() +{} + +void +SFLPhoneApp::handleArg() +{ + if (argc() > 1) { + PhoneLineManager::instance().makeNewCall(QString(argv()[1])); + } +} + +void +SFLPhoneApp::launch() +{ +// if(mLauncher) { +// mLauncher->start(); +// } +} + +void +SFLPhoneApp::initConnections(SFLPhoneWindow *w) +{ + // We connect the phone line buttons to the PhoneLineManager + unsigned int i = 0; + for(std::list< PhoneLineButton * >::iterator pos = w->mPhoneLineButtons.begin(); + pos != w->mPhoneLineButtons.end(); + pos++) { + PhoneLine *line = PhoneLineManager::instance().getPhoneLine(i); + QObject::connect(*pos, SIGNAL(selected(unsigned int)), + &PhoneLineManager::instance(), SLOT(selectLine(unsigned int))); + QObject::connect(*pos, SIGNAL(unselected(unsigned int)), + &PhoneLineManager::instance(), SLOT(unselectLine(unsigned int))); + QObject::connect(line, SIGNAL(selected(bool)), + *pos, SLOT(setOn(bool))); + QObject::connect(line, SIGNAL(backgrounded()), + *pos, SLOT(suspend())); + QObject::connect(line, SIGNAL(peerUpdated(QString)), + *pos, SLOT(setToolTip(QString))); + QObject::connect(line, SIGNAL(peerCleared()), + *pos, SLOT(clearToolTip())); + + i++; + } + + + QObject::connect(w, SIGNAL(needRegister()), + &PhoneLineManager::instance(), SLOT(registerToServer())); + //QObject::connect(&PhoneLineManager::instance(), SIGNAL(registered()), + // w, SIGNAL(registered())); + QObject::connect(w->mOk, SIGNAL(clicked()), + &PhoneLineManager::instance(), SLOT(call())); + QObject::connect(w->mMute, SIGNAL(toggled(bool)), + &PhoneLineManager::instance(), SLOT(mute(bool))); + QObject::connect(w->mDtmf, SIGNAL(toggled(bool)), + mKeypad, SLOT(setShown(bool))); + QObject::connect(mKeypad, SIGNAL(hidden()), + w->mDtmf, SLOT(release())); + QObject::connect(w->mSetup, SIGNAL(clicked()), + &PhoneLineManager::instance(), SLOT(setup())); + QObject::connect(w->mHangup, SIGNAL(clicked()), + &PhoneLineManager::instance(), SLOT(hangup())); + QObject::connect(w->mHold, SIGNAL(clicked()), + &PhoneLineManager::instance(), SLOT(hold())); + QObject::connect(w->mClear, SIGNAL(clicked()), + &PhoneLineManager::instance(), SLOT(clear())); + QObject::connect(w->mTransfer, SIGNAL(clicked()), + &PhoneLineManager::instance(), SLOT(transfer())); + QObject::connect(w->mRedial, SIGNAL(clicked()), + &PhoneLineManager::instance(), SLOT(redial())); + + QObject::connect(w, SIGNAL(keyPressed(Qt::Key)), + &PhoneLineManager::instance(), SLOT(sendKey(Qt::Key))); + + QObject::connect(w, SIGNAL(shortcutPressed(QKeyEvent*)), + this, SLOT(shortcutPressed(QKeyEvent*))); + + + // Keypad connections + QObject::connect(mKeypad, SIGNAL(keyPressed(Qt::Key)), + &PhoneLineManager::instance(), SLOT(sendKey(Qt::Key))); + + // LCD Connections. + QObject::connect(&PhoneLineManager::instance(), SIGNAL(lineStatusSet(QString)), + w->mLcd, SLOT(setLineStatus(QString))); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(unselectedLineStatusSet(QString)), + w->mLcd, SLOT(setUnselectedLineStatus(QString))); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(actionSet(QString)), + w->mLcd, SLOT(setAction(QString))); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(globalStatusSet(QString)), + w->mLcd, SLOT(setGlobalStatus(QString))); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(bufferStatusSet(QString)), + w->mLcd, SLOT(setBufferStatus(QString))); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(talkingStarted(QTime)), + w->mLcd, SLOT(setLineTimer(QTime))); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(talkingStopped()), + w->mLcd, SLOT(clearLineTimer())); + + + //Volume connections + QObject::connect(w->mVolume, SIGNAL(valueUpdated(int)), + &PhoneLineManager::instance(), SLOT(setVolume(int))); + QObject::connect(w->mMicVolume, SIGNAL(valueUpdated(int)), + &PhoneLineManager::instance(), SLOT(setMicVolume(int))); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(volumeUpdated(int)), + w->mVolume, SLOT(setValue(int))); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(micVolumeUpdated(int)), + w->mMicVolume, SLOT(setValue(int))); + + + //Line events connections + QObject::connect(&PhoneLineManager::instance(), SIGNAL(disconnected()), + w, SLOT(askReconnect())); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(disconnected()), + w, SLOT(show())); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(connected()), + w, SLOT(show())); + QObject::connect(w, SIGNAL(reconnectAsked()), + &PhoneLineManager::instance(), SLOT(connect())); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(stopped()), + w, SLOT(close())); + QObject::connect(w, SIGNAL(needToCloseDaemon()), + &PhoneLineManager::instance(), SLOT(stop())); + + //sflphoned launch + QObject::connect(w, SIGNAL(launchAsked()), + mLauncher, SLOT(start())); + QObject::connect(mLauncher, SIGNAL(error()), + w, SLOT(askLaunch())); + QObject::connect(mLauncher, SIGNAL(started()), + &PhoneLineManager::instance(), SLOT(connect())); + + QObject::connect(&PhoneLineManager::instance(), SIGNAL(gotErrorOnCallStatus(QString)), + w, SLOT(askResendStatus(QString))); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(gotErrorOnGetEvents(QString)), + w, SLOT(askResendStatus(QString))); + QObject::connect(w, SIGNAL(resendStatusAsked()), + &PhoneLineManager::instance(), SIGNAL(readyToSendStatus())); + + + //Configuration events. + QObject::connect(&ConfigurationManager::instance(), SIGNAL(updated()), + w, SLOT(showSetup())); + QObject::connect(&ConfigurationManager::instance(), SIGNAL(ringtonesUpdated()), + w, SIGNAL(ringtonesUpdated())); + QObject::connect(&ConfigurationManager::instance(), SIGNAL(audioDevicesUpdated()), + w, SIGNAL(audioDevicesUpdated())); + QObject::connect(&ConfigurationManager::instance(), SIGNAL(codecsUpdated()), + w, SIGNAL(codecsUpdated())); + //QObject::connect(&ConfigurationManager::instance(), SIGNAL(saved()), + // w, SLOT(hideSetup())); + + QObject::connect(w->mLcd, SIGNAL(midClicked()), this, SLOT(paste())); + +} + +void +SFLPhoneApp::loadSkin() +{ + SkinManager::instance().setApplication(this); + SkinManager::instance().load(); +} + +void +SFLPhoneApp::paste() +{ +// Seen on: http://doc.trolltech.com/3.3/showimg-example.html#x1078 +#ifndef QT_NO_MIMECLIPBOARD + QString text = QApplication::clipboard()->text(); + if ( !text.isEmpty() && !text.isNull() ) { + DebugOutput::instance() << QObject::tr("paste %1\n").arg(text); + PhoneLineManager::instance().makeNewCall(text); + } +#endif +} + +void +SFLPhoneApp::shortcutPressed(QKeyEvent* e) { + if (e && e->state() & Qt::ControlButton) { + switch(e->key()) { + case Qt::Key_V: + paste(); + break; + } + } +} diff --git a/src/gui/qt/SFLPhoneApp.hpp b/src/gui/qt/SFLPhoneApp.hpp new file mode 100644 index 0000000000..5f7acab18b --- /dev/null +++ b/src/gui/qt/SFLPhoneApp.hpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Yan Morin <yan.morin@savoirfairelinux.com> + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SFLPHONEAPP_HPP__ +#define __SFLPHONEAPP_HPP__ + +#include <qapplication.h> +#include <qsettings.h> +#include <qevent.h> + +#include "PhoneLineManager.hpp" +#include "Session.hpp" +#include "Account.hpp" + +class SFLPhoneWindow; +class Launcher; +class NumericKeypad; + +class SFLPhoneApp : public QApplication +{ + Q_OBJECT + +public: + SFLPhoneApp(int argc, char **argv); + virtual ~SFLPhoneApp(); + + /** + * This function will make the widgets + * connections. + */ + void initConnections(SFLPhoneWindow *w); + void loadSkin(); + + void launch(); + +public slots: + /** + * Handle argc/argv if any left + */ + void handleArg(); + void paste(); + void shortcutPressed(QKeyEvent* e); + +private: + + Launcher *mLauncher; + NumericKeypad *mKeypad; +}; + +#endif diff --git a/src/gui/qt/SFLPhoneWindow.cpp b/src/gui/qt/SFLPhoneWindow.cpp new file mode 100644 index 0000000000..673c369a0b --- /dev/null +++ b/src/gui/qt/SFLPhoneWindow.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Yan Morin <yan.morin@savoirfairelinux.com> + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "SFLPhoneWindow.hpp" + +#include <qbitmap.h> + +//To test if we are in QT4 +#ifdef QT3_SUPPORT +#include <QIcon> +#endif + + +#include <qlabel.h> +#include <qmessagebox.h> +#include <qevent.h> +#include <qpixmap.h> +#include <iostream> + +#include "globals.h" +#include "JPushButton.hpp" +#include "PhoneLineButton.hpp" +#include "SFLLcd.hpp" +#include "VolumeControl.hpp" + +#define LOGO_IMAGE "logo_ico.png" +#define BACKGROUND_IMAGE "main.png" +#define VOLUME_IMAGE "volume.png" + + +SFLPhoneWindow::SFLPhoneWindow() +#ifdef QT3_SUPPORT + : QMainWindow(NULL, Qt::FramelessWindowHint) +#else + : QMainWindow(NULL, NULL, + Qt::WDestructiveClose | + Qt::WStyle_Customize | + Qt::WStyle_NoBorder) +#endif +{ + mLastWindowPos = pos(); + mSetupPanel = new ConfigurationPanel(this, "ConfigurationPanel"); + connect(this, SIGNAL(ringtonesUpdated()), + mSetupPanel, SLOT(updateRingtones())); + connect(this, SIGNAL(audioDevicesUpdated()), + mSetupPanel, SLOT(updateAudioDevices())); + connect(this, SIGNAL(codecsUpdated()), + mSetupPanel, SLOT(updateCodecs())); + connect(mSetupPanel, SIGNAL(needRegister()), + this, SIGNAL(needRegister())); + + // Initialize the background image + mMain = new QLabel(this); + QPixmap main(JPushButton::transparize(BACKGROUND_IMAGE)); + mMain->setPixmap(main); + if(main.hasAlpha()) { + setMask(*main.mask()); + } + + mPaintTimer = new QTimer(this); + connect(mPaintTimer, SIGNAL(timeout()), + this, SLOT(delayedPaint())); + mPaintTimer->start(50); + + + resize(main.size()); + mMain->resize(main.size()); + + QPixmap logo(QPixmap::fromMimeSource(LOGO_IMAGE)); +#ifdef QIcon + setWindowIcon(QIcon(logo)); +#else + setIcon(logo); +#endif + + mLastPos = pos(); + + initGUIButtons(); + initWindowButtons(); + initLineButtons(); + initLCD(); +} + +SFLPhoneWindow::~SFLPhoneWindow() +{} + +void +SFLPhoneWindow::initLCD() +{ + mLcd = new SFLLcd(mMain); + mLcd->show(); +} + +void +SFLPhoneWindow::initGUIButtons() +{ + mHangup = new QPushButton(QObject::tr("Hangup"), mMain, "hangup"); + mHold = new QPushButton(QObject::tr("Hold"), mMain, "hold"); + mOk = new QPushButton(QObject::tr("Ok"), mMain, "ok"); + mClear = new QPushButton(QObject::tr("Clear"), mMain, "clear"); + mMute = new QPushButton(QObject::tr("Mute"), mMain, "mute"); + mMute->setToggleButton(true); + mDtmf = new QPushButton(QObject::tr("DTMF"), mMain, "dtmf"); + mDtmf->setToggleButton(true); + mSetup = new QPushButton(QObject::tr("Setup"), mMain, "setup"); + mTransfer = new QPushButton(QObject::tr("Transfer"), mMain, "transfer"); + mRedial = new QPushButton(QObject::tr("Redial"), mMain, "redial"); + mVolume = new VolumeControl(QString(VOLUME_IMAGE), + mMain); + mVolume->setOrientation(VolumeControl::Vertical); + mVolume->move(365,91); + QObject::connect(mVolume, SIGNAL(valueUpdated(int)), + this, SIGNAL(volumeUpdated(int))); + + mMicVolume = new VolumeControl(QString(VOLUME_IMAGE), + mMain); + mMicVolume->setOrientation(VolumeControl::Vertical); + mMicVolume->move(347,91); + QObject::connect(mVolume, SIGNAL(valueUpdated(int)), + this, SIGNAL(micVolumeUpdated(int))); + +} + +void +SFLPhoneWindow::initLineButtons() +{ + for(int i = 0; i < NB_PHONELINES; i++) { + PhoneLineButton *line = new PhoneLineButton(i, mMain); + mPhoneLineButtons.push_back(line); + } +} + +void SFLPhoneWindow::initWindowButtons() +{ + mCloseButton = new QPushButton(QObject::tr("Close"), mMain, "close"); + QObject::connect(mCloseButton, SIGNAL(clicked()), + this, SLOT(finish())); + mMinimizeButton = new QPushButton(QObject::tr("Minimize"), mMain, "minimize"); + QObject::connect(mMinimizeButton, SIGNAL(clicked()), + this, SLOT(showMinimized())); +} + +void +SFLPhoneWindow::keyPressEvent(QKeyEvent *e) { + // Misc. key + if (e->state() & Qt::ControlButton || e->key() == Qt::Key_Control) { + emit shortcutPressed(e); + } else { + emit keyPressed(Qt::Key(e->key())); + } +} + +void +SFLPhoneWindow::finish() +{ + emit needToCloseDaemon(); +} + +void +SFLPhoneWindow::askReconnect() +{ + QMessageBox::critical(NULL, + tr("SFLPhone error"), + tr("We got an error launching sflphone. Check the debug \n" + "output with \"[sflphoned]\" for more details. The \n" + "application will close."), + tr("Quit")); + close(); +} + +void +SFLPhoneWindow::askLaunch() +{ + QMessageBox::critical(NULL, + tr("SFLPhone daemon problem"), + tr("The SFLPhone daemon couldn't be started. Check \n" + "if sflphoned is in your PATH. The application will \n" + "close.\n"), + tr("Quit")); + close(); +} + + +void +SFLPhoneWindow::showSetup() +{ + mSetupPanel->generate(); + mSetupPanel->show(); +} + +void +SFLPhoneWindow::hideSetup() +{ + mSetupPanel->hide(); +} + +void +SFLPhoneWindow::askResendStatus(QString message) +{ + int ret = QMessageBox::critical(NULL, + tr("SFLPhone status error"), + tr("The server returned an error for the lines status.\n" + "\n%1\n\n" + "Do you want to try to resend this command? If not,\n" + "the application will close.").arg(message), + QMessageBox::Retry | QMessageBox::Default, + QMessageBox::No | QMessageBox::Escape); + if (ret == QMessageBox::Retry) { + emit resendStatusAsked(); + } + else { + close(); + } +} + +void +SFLPhoneWindow::mousePressEvent(QMouseEvent *e) +{ + mLastPos = e->pos(); +} + +void +SFLPhoneWindow::mouseMoveEvent(QMouseEvent *e) +{ + // Note that moving the windows is very slow + // 'cause it redraw the screen each time. + // Usually it doesn't. We could do it by a timer. + delayedMove(e->globalPos() - mLastPos); +} + +void +SFLPhoneWindow::delayedMove(const QPoint &point) +{ + mLastWindowPos = point; +} + +void +SFLPhoneWindow::delayedPaint() +{ + if(pos() != mLastWindowPos) { + move(mLastWindowPos); + } +} diff --git a/src/gui/qt/SFLPhoneWindow.hpp b/src/gui/qt/SFLPhoneWindow.hpp new file mode 100644 index 0000000000..952f8ddcd0 --- /dev/null +++ b/src/gui/qt/SFLPhoneWindow.hpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Yan Morin <yan.morin@savoirfairelinux.com> + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qlabel.h> +#include <qmainwindow.h> +#include <qobject.h> +#include <qpoint.h> +#include <qpushbutton.h> +#include <qtimer.h> +#include <list> + +#include "ConfigurationPanel.h" +#include "PhoneLineManager.hpp" + +class JPushButton; +class PhoneLineButton; +class SFLLcd; +class VolumeControl; + +class SFLPhoneWindow : public QMainWindow +{ + Q_OBJECT; + + friend class SFLPhoneApp; + +public: + SFLPhoneWindow(); + ~SFLPhoneWindow(); + +private: + void initLCD(); + void initGUIButtons(); + void initLineButtons(); + void initWindowButtons(); + +signals: + void keyPressed(Qt::Key); + void shortcutPressed(QKeyEvent *e); + void launchAsked(); + void reconnectAsked(); + void resendStatusAsked(); + void volumeUpdated(int); + void micVolumeUpdated(int); + void needToCloseDaemon(); + void ringtonesUpdated(); + void audioDevicesUpdated(); + void codecsUpdated(); + void needRegister(); + +public slots: + void delayedMove(const QPoint &point); + void delayedPaint(); + + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + + /** + * This function will prompt a message box, to ask + * if the user want to reconnect to sflphoned. + */ + void askReconnect(); + + /** + * This function will prompt a message box, to ask + * if the user want to launch sflphoned. + */ + void askLaunch(); + + /** + * This function will ask if you want to close + * sflphoned. + */ + void finish(); + + /** + * This function will prompt a message box, to ask + * if the user want to resend the getcallstatus request. + */ + void askResendStatus(QString); + + void showSetup(); + void hideSetup(); + +protected: + void keyPressEvent(QKeyEvent *e); + +private: + std::list< PhoneLineButton * > mPhoneLineButtons; + + QPushButton *mCloseButton; + QPushButton *mMinimizeButton; + + QPushButton *mHangup; + QPushButton *mHold; + QPushButton *mOk; + QPushButton *mClear; + QPushButton *mMute; + QPushButton *mDtmf; + QPushButton *mSetup; + QPushButton *mTransfer; + QPushButton *mRedial; + + VolumeControl *mVolume; + VolumeControl *mMicVolume; + + SFLLcd *mLcd; + QLabel *mMain; + + QPoint mLastPos; + QPoint mLastWindowPos; + QTimer *mPaintTimer; + + ConfigurationPanel *mSetupPanel; +}; diff --git a/src/gui/qt/SFLRequest.cpp b/src/gui/qt/SFLRequest.cpp new file mode 100644 index 0000000000..e7a7ff2e87 --- /dev/null +++ b/src/gui/qt/SFLRequest.cpp @@ -0,0 +1,417 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <iostream> +#include <memory> // for std::auto_ptr +#include <sstream> +#include <string> +#include <qstring.h> + +#include "globals.h" +#include "CallManager.hpp" +#include "CallStatus.hpp" +#include "CallStatusFactory.hpp" +#include "ConfigurationManager.hpp" +#include "PhoneLine.hpp" +#include "PhoneLineLocker.hpp" +#include "PhoneLineManager.hpp" +#include "SFLRequest.hpp" + +EventRequest::EventRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : Request(sequenceId, command, args) +{} + + +void +EventRequest::onError(const QString &code, const QString &message) +{ + DebugOutput::instance() << QObject::tr("EventRequest error: (%1) %1\n") + .arg(code) + .arg(message); + PhoneLineManager::instance().errorOnGetEvents(message); +} + +void +EventRequest::onEntry(const QString &code, const QString &message) +{ + std::auto_ptr< Event > + e(EventFactory::instance().create(code, Request::parseArgs(message))); + e->execute(); +} + +void +EventRequest::onSuccess(const QString &code, const QString &message) +{ + DebugOutput::instance() << QObject::tr("EventRequest success: (%1) %1\n") + .arg(code) + .arg(message); + PhoneLineManager::instance().connect(); +} + +CallStatusRequest::CallStatusRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : Request(sequenceId, command, args) +{} + + +void +CallStatusRequest::onError(const QString &code, const QString &message) +{ + DebugOutput::instance() << QObject::tr("CallStatusRequest error: (%1) %1\n") + .arg(code) + .arg(message); + PhoneLineManager::instance().errorOnCallStatus(message); +} + +void +CallStatusRequest::onEntry(const QString &code, const QString &message) +{ + std::auto_ptr< Event > + e(EventFactory::instance().create(code, Request::parseArgs(message))); + e->execute(); +} + +void +CallStatusRequest::onSuccess(const QString &code, const QString &message) +{ + DebugOutput::instance() << QObject::tr("CallStatusRequest success: (%1) %1\n") + .arg(code) + .arg(message); + if(code == "206") { + std::list< QString > args = Request::parseArgs(message); + if(args.size() >= 2) { + PhoneLineManager::instance().selectLine(*args.begin(), true); + } + else { + DebugOutput::instance() << QObject::tr("CallStatusRequest Error: cannot get current line.\n"); + } + } + PhoneLineManager::instance().handleEvents(); +} + + +PermanentRequest::PermanentRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : CallRelatedRequest(sequenceId, command, args) +{} + +void +PermanentRequest::onError(Call call, + const QString &, + const QString &message) +{ + DebugOutput::instance() << QObject::tr("PermanentRequest: Error: %1").arg(toString()); + PhoneLine *line = PhoneLineManager::instance().getLine(call); + if(line) { + PhoneLineLocker guard(line, false); + line->error(message); + line->setAction(""); + } + else { + DebugOutput::instance() << + QObject::tr("We received an error on a call " + "that doesn't have a phone line (%1).\n") + .arg(call.id()); + } +} + +void +PermanentRequest::onEntry(Call call, + const QString &, + const QString &message) +{ + PhoneLine *line = PhoneLineManager::instance().getLine(call); + if(line) { + PhoneLineLocker guard(line, false); + line->setLineStatus(message); + line->setAction(""); + } + else { + DebugOutput::instance() << + QObject::tr("We received a status on a call related request " + "that doesn't have a phone line (%1).\n") + .arg(call.id()); + } +} + +void +PermanentRequest::onSuccess(Call call, + const QString &, + const QString &message) +{ + PhoneLine *line = PhoneLineManager::instance().getLine(call); + if(line) { + PhoneLineLocker guard(line, false); + line->setLineStatus(message); + line->setAction(""); + } + else { + DebugOutput::instance() << + QObject::tr("We received a success on a call related request " + "that doesn't have a phone line (%1).\n") + .arg(call.id()); + } +} + +TemporaryRequest::TemporaryRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : CallRelatedRequest(sequenceId, command, args) +{} + +void +TemporaryRequest::onError(Call call, + const QString &code, + const QString &message) +{ + onSuccess(call, code, message); +} + +void +TemporaryRequest::onEntry(Call call, + const QString &code, + const QString &message) +{ + onSuccess(call, code, message); +} + +void +TemporaryRequest::onSuccess(Call call, + const QString &, + const QString &message) +{ + PhoneLine *line = PhoneLineManager::instance().getLine(call); + if(line) { + PhoneLineLocker guard(line, false); + line->setTempAction(message); + } + else { + DebugOutput::instance() << + QObject::tr("We received an answer on a temporary call " + "related request that doesn't have a phone " + "line (%1).\n") + .arg(call.id()); + } +} + +CallRequest::CallRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : AccountRequest(sequenceId, command, args) +{ + + std::list< QString >::const_iterator pos = args.begin(); + pos++; + mCallId = *pos; +} + +void +CallRequest::onError(Account, + const QString &, + const QString &message) +{ + if(CallManager::instance().exist(mCallId)) { + PhoneLine *line = + PhoneLineManager::instance().getLine(CallManager::instance().getCall(mCallId)); + if(line) { + PhoneLineLocker guard(line, false); + line->error(message); + } + else { + DebugOutput::instance() << + QObject::tr("We received an error on a call " + "that doesn't have a phone line (%1).\n") + .arg(mCallId); + } + } + else { + DebugOutput::instance() << QObject::tr("CallRequest: Trying to retreive an unregistred call (%1)\n").arg(mCallId); + } +} + +void +CallRequest::onEntry(Account, + const QString &, + const QString &message) +{ + if(CallManager::instance().exist(mCallId)) { + PhoneLine *line = + PhoneLineManager::instance().getLine(CallManager::instance().getCall(mCallId)); + if(line) { + PhoneLineLocker guard(line, false); + line->setLineStatus(message); + } + else { + DebugOutput::instance() << + QObject::tr("We received a status on a call related request " + "that doesn't have a phone line (%1).\n") + .arg(mCallId); + } + } + else { + DebugOutput::instance() << QObject::tr("CallRequest: Trying to retreive an unregistred call (%1)\n").arg(mCallId); + } +} + +void +CallRequest::onSuccess(Account, + const QString &, + const QString &message) +{ + if(CallManager::instance().exist(mCallId)) { + PhoneLine *line = + PhoneLineManager::instance().getLine(CallManager::instance().getCall(mCallId)); + if(line) { + PhoneLineLocker guard(line, false); + line->setLineStatus(message); + } + else { + DebugOutput::instance() << + QObject::tr("We received a success on a call related request " + "that doesn't have a phone line (%1).\n") + .arg(mCallId); + } + } + else { + DebugOutput::instance() << QObject::tr("CallRequest: Trying to retreive an unregistred call (%1)\n").arg(mCallId); + } +} + + + +ConfigGetAllRequest::ConfigGetAllRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : Request(sequenceId, command, args) +{} + + +void +ConfigGetAllRequest::onError(const QString &code, const QString &message) +{ + DebugOutput::instance() << QObject::tr("ConfigGetAllRequest error: (%1) %1\n") + .arg(code) + .arg(message); +} + +void +ConfigGetAllRequest::onEntry(const QString &, const QString &message) +{ + std::list< QString > args = Request::parseArgs(message); + if(args.size() >= 3) { + QString section, variable, type, def, val; + section = *args.begin(); + args.pop_front(); + variable = *args.begin(); + args.pop_front(); + type = *args.begin(); + args.pop_front(); + if(args.size() >= 1) { + val = *args.begin(); + args.pop_front(); + } + if(args.size() >= 1) { + def = *args.begin(); + args.pop_front(); + } + ConfigurationManager::instance().add(ConfigEntry(section, variable, type, def, val)); + } +} + +void +ConfigGetAllRequest::onSuccess(const QString &, const QString &) +{ + ConfigurationManager::instance().complete(); +} + + +ConfigSaveRequest::ConfigSaveRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : Request(sequenceId, command, args) +{} + + +void +ConfigSaveRequest::onError(const QString &code, const QString &message) +{ + DebugOutput::instance() << QObject::tr("ConfigSaveRequest error: (%1) %1\n") + .arg(code) + .arg(message); +} + +void +ConfigSaveRequest::onSuccess(const QString &, const QString &) +{ + ConfigurationManager::instance().finishSave(); +} + +StopRequest::StopRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : Request(sequenceId, command, args) +{} + + +void +StopRequest::onError(const QString &code, const QString &message) +{ + DebugOutput::instance() << QObject::tr("StopRequest error: (%1) %1\n") + .arg(code) + .arg(message); +} + +void +StopRequest::onSuccess(const QString &, const QString &) +{ + PhoneLineManager::instance().finishStop(); +} + +SignalizedRequest::SignalizedRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args) + : Request(sequenceId, command, args) +{} + +void +SignalizedRequest::onError(const QString &code, + const QString &message) +{ + emit error(message, code); +} + +void +SignalizedRequest::onEntry(const QString &code, + const QString &message) +{ + emit entry(message, code); +} + +void +SignalizedRequest::onSuccess(const QString &code, + const QString &message) +{ + emit success(message, code); +} + diff --git a/src/gui/qt/SFLRequest.hpp b/src/gui/qt/SFLRequest.hpp new file mode 100644 index 0000000000..305cbec132 --- /dev/null +++ b/src/gui/qt/SFLRequest.hpp @@ -0,0 +1,279 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + + + +#ifndef SFLPHONEGUI_SFLREQUEST_HPP +#define SFLPHONEGUI_SFLREQUEST_HPP + +#include <list> +#include "Request.hpp" + +class EventRequest : public Request +{ +public: + EventRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + + virtual ~EventRequest(){} + + /** + * This function will be called when the request + * receive its answer, if the request didn't successfully + * ended. When we have an error on an EventRequest, we should + * quit the program. + */ + virtual void onError(const QString &code, const QString &message); + + /** + * This function will be called when the request + * receive an answer, but there's other answers to come. + * This will be dispatched to the valid event. + */ + virtual void onEntry(const QString &code, const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the request successfully + * ended. The event handling is gone, so we should + * quit. + */ + virtual void onSuccess(const QString &code, const QString &message); + +}; + +class CallStatusRequest : public Request +{ +public: + CallStatusRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + + virtual ~CallStatusRequest(){} + + /** + * This function will be called when the request + * receive its answer, if the request didn't successfully + * ended. When we have an error on an EventRequest, we should + * quit the program. + */ + virtual void onError(const QString &code, const QString &message); + + /** + * This function will be called when the request + * receive an answer, but there's other answers to come. + * This will be dispatched to the valid event. + */ + virtual void onEntry(const QString &code, const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the request successfully + * ended. The event handling is gone, so we should + * quit. + */ + virtual void onSuccess(const QString &code, const QString &message); + +}; + + +class CallRequest : public AccountRequest +{ + public: + CallRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + /** + * This function will be called when the request + * receive its answer, if the request didn't successfully + * ended. + */ + virtual void onError(Account account, + const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive an answer, but there's other answers to come. + */ + virtual void onEntry(Account account, + const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the request successfully + * ended. + */ + virtual void onSuccess(Account account, + const QString &code, + const QString &message); + +private: + QString mCallId; +}; + + +class PermanentRequest : public CallRelatedRequest +{ + public: + PermanentRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + + /** + * This function will be called when the request + * receive its answer, if the request didn't successfully + * ended. + */ + virtual void onError(Call call, + const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive an answer, but there's other answers to come. + */ + virtual void onEntry(Call call, + const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the request successfully + * ended. + */ + virtual void onSuccess(Call call, + const QString &code, + const QString &message); +}; + +class TemporaryRequest : public CallRelatedRequest +{ + public: + TemporaryRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + + /** + * This function will be called when the request + * receive its answer, if the request didn't successfully + * ended. + */ + virtual void onError(Call call, + const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive an answer, but there's other answers to come. + */ + virtual void onEntry(Call call, + const QString &code, + const QString &message); + + /** + * This function will be called when the request + * receive its answer, if the request successfully + * ended. + */ + virtual void onSuccess(Call call, + const QString &code, + const QString &message); +}; + +class ConfigGetAllRequest : public Request +{ +public: + ConfigGetAllRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + + virtual ~ConfigGetAllRequest(){} + + + virtual void onError(const QString &code, const QString &message); + virtual void onEntry(const QString &code, const QString &message); + virtual void onSuccess(const QString &code, const QString &message); +}; + +class ConfigSaveRequest : public Request +{ +public: + ConfigSaveRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + + virtual ~ConfigSaveRequest(){} + + + virtual void onError(const QString &code, const QString &message); + virtual void onSuccess(const QString &code, const QString &message); +}; + +class StopRequest : public Request +{ +public: + StopRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + + virtual ~StopRequest(){} + virtual void onError(const QString &code, const QString &message); + virtual void onSuccess(const QString &code, const QString &message); +}; + + +class SignalizedRequest : public Request +{ + Q_OBJECT + +public: + SignalizedRequest(const QString &sequenceId, + const QString &command, + const std::list< QString > &args); + + virtual void onError(const QString &code, const QString &message); + virtual void onEntry(const QString &code, const QString &message); + virtual void onSuccess(const QString &code, const QString &message); + +signals: + /** + * Be aware that the first string is the message, + * and the second is the code. This is done that + * way because usually the message is more important + * than the code. + */ + void error(QString, QString); + void success(QString, QString); + void entry(QString, QString); +}; + +#endif diff --git a/src/gui/qt/Session.cpp b/src/gui/qt/Session.cpp new file mode 100644 index 0000000000..02d80a6e1e --- /dev/null +++ b/src/gui/qt/Session.cpp @@ -0,0 +1,181 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <list> +#include <iostream> +#include <qstring.h> + +#include "Session.hpp" +#include "Requester.hpp" +#include "SessionIOFactory.hpp" + + +Session::Session(const QString &id) + : mId(id) +{} + +Session::Session() +{ + mId = Requester::instance().generateSessionId(); + SessionIO *s = SessionIOFactory::instance().create(); + Requester::instance().registerSession(mId, s); +} + +QString +Session::id() const +{ + return mId; +} + +Request * +Session::playTone() const +{ + return Requester::instance().send(mId, "playtone", std::list< QString >()); +} + +Request * +Session::stopTone() const +{ + return Requester::instance().send(mId, "stoptone", std::list< QString >()); +} + +void +Session::connect() const +{ + return Requester::instance().connect(mId); +} + + +Request * +Session::getEvents() const +{ + return Requester::instance().send(mId, "getevents", std::list< QString >()); +} + + +Request * +Session::configSet(const QString §ion, + const QString &name, + const QString &value) const +{ + std::list< QString > args; + args.push_back(section); + args.push_back(name); + args.push_back(value); + return Requester::instance().send(mId, "configset", args); +} + + +Request * +Session::configGetAll() const +{ + return Requester::instance().send(mId, "configgetall", std::list< QString >()); +} + +Request * +Session::configSave() const +{ + return Requester::instance().send(mId, "configsave", std::list< QString >()); +} + +Request * +Session::close() const +{ + return Requester::instance().send(mId, "close", std::list< QString >()); +} + +Request * +Session::stop() const +{ + return Requester::instance().send(mId, "stop", std::list< QString >()); +} + +Request * +Session::mute() const +{ + return Requester::instance().send(mId, "mute", std::list< QString >()); +} + +Request * +Session::unmute() const +{ + return Requester::instance().send(mId, "unmute", std::list< QString >()); +} + +Request * +Session::volume(unsigned int volume) const +{ + std::list< QString > args; + args.push_back(QString("%1").arg(volume)); + return Requester::instance().send(mId, "setspkrvolume", args); +} + +Request * +Session::micVolume(unsigned int volume) const +{ + std::list< QString > args; + args.push_back(QString("%1").arg(volume)); + return Requester::instance().send(mId, "setmicvolume", args); +} + +Request * +Session::getCallStatus() const +{ + return Requester::instance().send(mId, "getcallstatus", std::list< QString >()); +} + +Request * +Session::playDtmf(char c) const +{ + QString s; + s += c; + std::list< QString > args; + args.push_back(s); + return Requester::instance().send(mId, "playdtmf", args); +} + +Request * +Session::list(const QString &category) const +{ + std::list< QString > args; + args.push_back(category); + return Requester::instance().send(mId, "list", args); +} + +Request * +Session::registerToServer() const +{ + std::list< QString > args; + args.push_back(getDefaultAccount().id()); + return Requester::instance().send(mId, "register", args); +} + +Account +Session::getAccount(const QString &name) const +{ + return Account(mId, name); +} + +Account +Session::getDefaultAccount() const +{ + return Account(mId, QString("mydefaultaccount")); +} + diff --git a/src/gui/qt/Session.hpp b/src/gui/qt/Session.hpp new file mode 100644 index 0000000000..1d79d63144 --- /dev/null +++ b/src/gui/qt/Session.hpp @@ -0,0 +1,122 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef SFLPHONEGUI_SESSION_H +#define SFLPHONEGUI_SESSION_H + +#include <qstring.h> + +#include "Account.hpp" + +class Session +{ + public: + Session(); + Session(const QString &id); + + /** + * retreive the account identified by name. + */ + Account getAccount(const QString &name) const; + + Account getDefaultAccount() const; + + /** + * This function will play a tone. This is + * just a ear candy. + */ + Request *playDtmf(char c) const; + + + /** + * This function will retreive the given list. + */ + Request *list(const QString &category) const; + + /** + * This function will register to receive events + */ + Request *getEvents() const; + + /** + * This function will ask for all calls status. + */ + Request *getCallStatus() const; + + /** + * This function will mute the microphone. + */ + Request *mute() const; + + /** + * This function will ask sflphoned to close + * the session. This will only close the session, + * so sflphoned will still be running after. + */ + Request *close() const; + + /** + * This function will register with the default account. + */ + Request *registerToServer() const; + + /** + * This function will stop sflphoned. + */ + Request *stop() const; + + Request *configSet(const QString §ion, + const QString &name, + const QString &value) const; + Request *configSave() const; + Request *configGetAll() const; + + /** + * This function will set the volume to + * the given percentage + */ + Request *volume(unsigned int volume) const; + + /** + * This function will set the mic volume to + * the given percentage + */ + Request *micVolume(unsigned int volume) const; + + /** + * This function will unmute the microphone. + */ + Request *unmute() const; + + /** + * This function will ask to the SessionIO + * linked to this session to connect. + */ + void connect() const; + + QString id() const; + Request *stopTone() const; + Request *playTone() const; + + private: + QString mId; +}; + +#endif diff --git a/src/gui/qt/SessionFactory.hpp b/src/gui/qt/SessionFactory.hpp new file mode 100644 index 0000000000..c2a474e6cd --- /dev/null +++ b/src/gui/qt/SessionFactory.hpp @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __FACTORY_HPP__ +#define __FACTORY_HPP__ + +template< T > +struct Creator +{ + virtual T *create(); +}; + +template< typename T > +class Factory +{ +public: + Factory(); + ~Factory(); + + /** + * This function will set the creator. The + * Factory owns the creator instance. + */ + void setCreator(Creator< T > *creator); + + /** + * It ask the creator to create a SessionIO. + * If there's no creator set, it will throw + * a std::logic_error. + */ + T *create(); + +private: + Creator< T > *mCreator; +} + +#include "Factory.inl" + +#endif diff --git a/src/gui/qt/SessionIO.hpp b/src/gui/qt/SessionIO.hpp new file mode 100644 index 0000000000..e845e8e00c --- /dev/null +++ b/src/gui/qt/SessionIO.hpp @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SESSIONIO_HPP__ +#define __SESSIONIO_HPP__ + +#include <qobject.h> +#include <qstring.h> + +/** + * This is the main class that will handle + * the IO. + */ +class SessionIO : public QObject +{ + Q_OBJECT + + public: + virtual ~SessionIO(){} + +public slots: + virtual void connect() {} + + /** + * You can use this function for sending request. + * The sending is non-blocking. This function will + * send the data as it is; it will NOT add an EOL. + * the stream will be "sync"ed. + */ + virtual void send(const QString &request) = 0; + + /** + * You can use this function to receive answers. + * This function will wait until there's an + * answer to be processed. + */ + virtual void receive(QString &answer) = 0; + +}; + + + +#endif + diff --git a/src/gui/qt/SessionIOFactory.hpp b/src/gui/qt/SessionIOFactory.hpp new file mode 100644 index 0000000000..af82d47a9e --- /dev/null +++ b/src/gui/qt/SessionIOFactory.hpp @@ -0,0 +1,31 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SESSIONIOFACTORY_HPP__ +#define __SESSIONIOFACTORY_HPP__ + +#include "utilspp/Singleton.hpp" +#include "Factory.hpp" +#include "SessionIO.hpp" + +typedef utilspp::SingletonHolder< Factory< SessionIO > > SessionIOFactory; + +#endif + diff --git a/src/gui/qt/SkinManager.hpp b/src/gui/qt/SkinManager.hpp new file mode 100644 index 0000000000..87ac798003 --- /dev/null +++ b/src/gui/qt/SkinManager.hpp @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author : Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SKIN_MANAGER_HPP__ +#define __SKIN_MANAGER_HPP__ + +#include "utilspp/Singleton.hpp" +#include "SkinManagerImpl.hpp" + +typedef utilspp::SingletonHolder< SkinManagerImpl > SkinManager; + +#endif + diff --git a/src/gui/qt/SkinManagerImpl.cpp b/src/gui/qt/SkinManagerImpl.cpp new file mode 100644 index 0000000000..87ec663f46 --- /dev/null +++ b/src/gui/qt/SkinManagerImpl.cpp @@ -0,0 +1,78 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "globals.h" +#include "DebugOutput.hpp" +#include "SkinManagerImpl.hpp" + +SkinManagerImpl::SkinManagerImpl() + : mApp(NULL) + , mHunter(DATADIR) +{ + mSettings.setPath("savoirfairelinux.com", PROGNAME); + mPaths = mSettings.readListEntry("SkinPaths"); +} + +void +SkinManagerImpl::setApplication(QApplication *app) +{ + mApp = app; +} + +void +SkinManagerImpl::load() +{ + load(mSettings.readEntry("Skin", "metal")); +} + +void +SkinManagerImpl::save() +{ + mSettings.writeEntry("Skin", mSkin); + mSettings.writeEntry("SkinPaths", mPaths); +} + +void +SkinManagerImpl::load(const QString &skin) +{ + mSkin = skin; + if(mApp) { + taxidermy::Taxidermist taxidermist = mHunter.getTaxidermist(skin); + taxidermist.update(mApp); + } +} + +QStringList +SkinManagerImpl::getSkins() +{ + return mHunter.getSkinNames(); +} + +void +SkinManagerImpl::addPath(const QString &path) +{ + mPaths.push_back(path); +} + +QStringList +SkinManagerImpl::getPaths() +{ + return mPaths; +} diff --git a/src/gui/qt/SkinManagerImpl.hpp b/src/gui/qt/SkinManagerImpl.hpp new file mode 100644 index 0000000000..b5a4c9f0bc --- /dev/null +++ b/src/gui/qt/SkinManagerImpl.hpp @@ -0,0 +1,69 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef __SKIN_MANAGER_IMPL_HPP__ +#define __SKIN_MANAGER_IMPL_HPP__ + +#include <qstring.h> +#include <qsettings.h> +#include <qapplication.h> + +#include "taxidermy/Hunter.hpp" + +class SkinManagerImpl +{ +public: + SkinManagerImpl(); + + public slots: + /** + * This function load a given skin. If the + * skin is invalid, nothing is done. + */ + void load(const QString &skin); + + /** + * This function load the default skin. If the + * skin is invalid, nothing is done. + */ + void load(); + + void save(); + + void setApplication(QApplication *app); + QString getCurrentSkin() + {return mSkin;} + + void addPath(const QString &path); + QStringList getSkins(); + QStringList getPaths(); + +private: + QApplication *mApp; + QSettings mSettings; + QString mSkin; + QStringList mPaths; + taxidermy::Hunter mHunter; + +}; + +#endif + diff --git a/src/gui/qt/TCPSessionIO.cpp b/src/gui/qt/TCPSessionIO.cpp new file mode 100644 index 0000000000..4b4321b41a --- /dev/null +++ b/src/gui/qt/TCPSessionIO.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "globals.h" +#include "DebugOutput.hpp" +#include "Requester.hpp" +#include "TCPSessionIO.hpp" + +#define NB_MAX_TRIES 4 + +TCPSessionIO::TCPSessionIO(const QString &hostname, Q_UINT16 port) + : mSocket(new QSocket(this)) + , mHostname(hostname) + , mPort(port) + , mNbConnectTries(0) +{ + mReconnectTimer = new QTimer(this); + QObject::connect(mReconnectTimer, SIGNAL(timeout()), + this, SLOT(connect())); + + QObject::connect(mSocket, SIGNAL(readyRead()), + this, SLOT(receive())); + QObject::connect(mSocket, SIGNAL(connected()), + this, SLOT(sendWaitingRequests())); + QObject::connect(mSocket, SIGNAL(connected()), + this, SLOT(resetConnectionTries())); + QObject::connect(mSocket, SIGNAL(connected()), + this, SIGNAL(connected())); + QObject::connect(mSocket, SIGNAL(connectionClosed()), + this, SIGNAL(disconnected())); + QObject::connect(mSocket, SIGNAL(error(int)), + this, SLOT(error(int))); +} + +TCPSessionIO::~TCPSessionIO() +{} + +void +TCPSessionIO::resetConnectionTries() +{ + mNbConnectTries = 0; +} + +void +TCPSessionIO::error(int err) +{ + mNbConnectTries++; + if(mNbConnectTries >= NB_MAX_TRIES) { + DebugOutput::instance() << QObject::tr("TCPSessionIO: Connection failed: %1\n") + .arg(err); + mNbConnectTries = 0; + emit disconnected(); + } + else { + mReconnectTimer->start(2000, true); + } + //mSocket->close(); +} + +void +TCPSessionIO::receive() +{ + QString s; + while(mSocket->canReadLine()) { + receive(s); + Requester::instance().receiveAnswer(s); + } +} + +void +TCPSessionIO::connect() +{ + DebugOutput::instance() << QObject::tr("TCPSessionIO: Tring to connect to %1:%2.\n") + .arg(mHostname) + .arg(mPort); + mSocket->connectToHost(mHostname, mPort); +} + +void +TCPSessionIO::sendWaitingRequests() +{ + DebugOutput::instance() << QObject::tr("TCPSessionIO: Connected.\n"); + QTextStream stream(mSocket); + while(mSocket->state() == QSocket::Connected && + mStack.size() > 0) { + stream << *mStack.begin(); + mStack.pop_front(); + mSocket->flush(); + } +} + +void +TCPSessionIO::send(const QString &request) +{ + QTextStream stream(mSocket); + if(mSocket->state() == QSocket::Connected) { + DebugOutput::instance() << QObject::tr("TCPSessioIO: Sending request to sflphone: %1") + .arg(request); + stream << request; + mSocket->flush(); + } + else { + mStack.push_back(request); + } +} + +void +TCPSessionIO::receive(QString &answer) +{ + if(mSocket->isReadable()) { + QTextStream stream(mSocket); + answer = stream.readLine(); + DebugOutput::instance() << QObject::tr("TCPSessionIO: Received answer from sflphone: %1\n") + .arg(answer); + } +} + + + + + + + diff --git a/src/gui/qt/TCPSessionIO.hpp b/src/gui/qt/TCPSessionIO.hpp new file mode 100644 index 0000000000..6ddf34df64 --- /dev/null +++ b/src/gui/qt/TCPSessionIO.hpp @@ -0,0 +1,101 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TCPSESSIONIO_HPP__ +#define __TCPSESSIONIO_HPP__ + +#include <qobject.h> +#include <qstring.h> +#include <qsocket.h> +#include <qtextstream.h> +#include <qtimer.h> +#include <list> + +#include "SessionIO.hpp" + +#ifdef QT3_SUPPORT +#include <Q3Socket> +typedef Q3Socket QSocket; +#else +#include <qsocket.h> +#endif + + +class TCPSessionIO : public SessionIO +{ + Q_OBJECT + +public: + TCPSessionIO(const QString &hostname, + Q_UINT16 port); + + virtual ~TCPSessionIO(); + +signals: + void connected(); + void disconnected(); + +public slots: + /** + * This function send the request that we were + * unable to send. + */ + void sendWaitingRequests(); + + /** + * Those function are the actual function + * that write to the socket. + */ + virtual void send(const QString &request); + + /** + * This function is called when we have + * incomming data on the socket. + */ + virtual void receive(); + + /** + * Those function are the actual function + * that read from the socket. + */ + virtual void receive(QString &answer); + virtual void connect(); + + void resetConnectionTries(); + + private slots: + /** + * This function is called when we have an error + * on the socket. + */ + void error(int); + +private: + QSocket *mSocket; + QString mHostname; + Q_UINT16 mPort; + + std::list< QString > mStack; + + unsigned int mNbConnectTries; + QTimer *mReconnectTimer; +}; + +#endif diff --git a/src/gui/qt/TCPSessionIOCreator.cpp b/src/gui/qt/TCPSessionIOCreator.cpp new file mode 100644 index 0000000000..7e34f64119 --- /dev/null +++ b/src/gui/qt/TCPSessionIOCreator.cpp @@ -0,0 +1,39 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "TCPSessionIOCreator.hpp" +#include "PhoneLineManager.hpp" + +TCPSessionIOCreator::TCPSessionIOCreator(const QString &hostname, + Q_UINT16 port) + : mHostname(hostname) + , mPort(port) +{} + +TCPSessionIO * +TCPSessionIOCreator::create() +{ + TCPSessionIO *t = new TCPSessionIO(mHostname, mPort); + QObject::connect(t, SIGNAL(connected()), + &PhoneLineManager::instance(), SIGNAL(connected())); + QObject::connect(t, SIGNAL(disconnected()), + &PhoneLineManager::instance(), SLOT(hasDisconnected())); + return t; +} diff --git a/src/gui/qt/TCPSessionIOCreator.hpp b/src/gui/qt/TCPSessionIOCreator.hpp new file mode 100644 index 0000000000..32b7abc7bd --- /dev/null +++ b/src/gui/qt/TCPSessionIOCreator.hpp @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TCPSESSIONIOCREATOR_HPP__ +#define __TCPSESSIONIOCREATOR_HPP__ + +#include "Factory.hpp" +#include "TCPSessionIO.hpp" + +class TCPSessionIOCreator : public Creator< SessionIO > +{ +public: + TCPSessionIOCreator(const QString &hostname, + Q_UINT16 port); + virtual ~TCPSessionIOCreator(){} + + virtual TCPSessionIO *create(); + +private: + QString mHostname; + Q_UINT16 mPort; +}; + +#endif diff --git a/src/gui/qt/TransparentWidget.cpp b/src/gui/qt/TransparentWidget.cpp new file mode 100644 index 0000000000..9d7f9cd125 --- /dev/null +++ b/src/gui/qt/TransparentWidget.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * (jean-philippe.barrette-lapierre@savoirfairelinux.com) + * + * This 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, + * or (at your option) any later version. + * + * This 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. + * + * You should have received a copy of the GNU General Public + * License along with dpkg; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qbitmap.h> +#include <qcolor.h> +#include <qdragobject.h> +#include <qmime.h> +#include <iostream> + +#include "DebugOutput.hpp" +#include "TransparentWidget.hpp" + + +TransparentWidget::TransparentWidget(const QString &pixmap, + QWidget* parent) + : QLabel(parent) +{ + mImage = transparize(pixmap); + setPixmap(mImage); + updateMask(this, mImage); + + resize(mImage.size()); +} + +TransparentWidget::TransparentWidget(QWidget* parent) + : QLabel(parent) +{} + +void +TransparentWidget::updateMask(QWidget *w, QPixmap image) +{ +#ifdef QT3_SUPPORT + if(image.hasAlpha()) { + w->setMask(image.mask()); + } +#else + if(image.mask()) { + w->setMask(*image.mask()); + } +#endif +} + +QPixmap +TransparentWidget::retreive(const QString &image) +{ + return QPixmap::fromMimeSource(image); +} + +QPixmap +TransparentWidget::transparize(const QSize &) +{ + /* + QImage image(size, QImage::Format_RGB32); + QColor c(12,32,35,123); + image.fill(c.rgb()); + + QPixmap p(QPixmap::fromImage(image)); + p.setMask(p.createHeuristicMask()); + //p.setMask(p.alphaChannel()); + */ + return QPixmap(); +} + +TransparentWidget::~TransparentWidget() +{} + + +void +TransparentWidget::setPaletteBackgroundPixmap(QWidget *w, const QString &pixmap) +{ + QPixmap p(transparize(pixmap)); + w->setPaletteBackgroundPixmap(p); + updateMask(w, p); +} + +QPixmap +TransparentWidget::transparize(const QString &image) +{ +#ifdef QT3_SUPPORT + QPixmap p(retreive(image)); + if (!p.mask()) { + if (p.hasAlphaChannel()) { + p.setMask(p.alphaChannel()); + } + else { + p.setMask(p.createHeuristicMask()); + } + } +#else + // QPixmap p(QPixmap::fromMimeSource(image)); + QImage img(QImage::fromMimeSource(image)); + QPixmap p; + p.convertFromImage(img); + + + QBitmap bm; + if (img.hasAlphaBuffer()) { + bm = img.createAlphaMask(); + } + else { + bm = img.createHeuristicMask(); + } + p.setMask(bm); +#endif + return p; +} + + diff --git a/src/gui/qt/TransparentWidget.hpp b/src/gui/qt/TransparentWidget.hpp new file mode 100644 index 0000000000..f0ca17d25c --- /dev/null +++ b/src/gui/qt/TransparentWidget.hpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * (jean-philippe.barrette-lapierre@savoirfairelinux.com) + * + * This 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, + * or (at your option) any later version. + * + * This 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. + * + * You should have received a copy of the GNU General Public + * License along with dpkg; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TRANSPARENT_WIDGET_HPP__ +#define __TRANSPARENT_WIDGET_HPP__ + +#include <qbitmap.h> +#include <qlabel.h> +#include <qpixmap.h> +#include <qimage.h> + +/** + * This class Emulate a PushButton but takes two + * images to display its state. + */ +class TransparentWidget : public QLabel +{ + Q_OBJECT + +public: + TransparentWidget(const QString &pixmap, + QWidget *parent); + TransparentWidget(QWidget *parent); + ~TransparentWidget(); + + static QPixmap retreive(const QString &size); + static QPixmap transparize(const QSize &size); + static QPixmap transparize(const QString &image); + static void setPaletteBackgroundPixmap(QWidget *w, const QString &pixmap); + + /** + * This function will update the mask of the widget + * to the QPixmap mask. + */ + static void updateMask(QWidget *w, QPixmap image); + + + bool hasAlpha() + {return mImage.hasAlpha();} + + QBitmap mask() const + {return *mImage.mask();} + +private: + QPixmap mImage; + +}; + +#endif diff --git a/src/gui/qt/Url.cpp b/src/gui/qt/Url.cpp new file mode 100644 index 0000000000..ac3549f830 --- /dev/null +++ b/src/gui/qt/Url.cpp @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <string> +#include <qurl.h> + +#include "Url.hpp" + +static uchar hex_to_int( uchar c ) +{ + if ( c >= 'A' && c <= 'F' ) + return c - 'A' + 10; + if ( c >= 'a' && c <= 'f') + return c - 'a' + 10; + if ( c >= '0' && c <= '9') + return c - '0'; + return 0; +} + +void Url::decode( QString& url ) +{ + int oldlen = url.length(); + if ( !oldlen ) + return; + + int newlen = 0; + + std::string newUrl; + + int i = 0; + while ( i < oldlen ) { + ushort c = url[ i++ ].unicode(); + if ( c == '%' ) { + c = hex_to_int( url[ i ].unicode() ) * 16 + hex_to_int( url[ i + 1 ].unicode() ); + i += 2; + } + else if ( c == '+' ) { + c = ' '; + } + newUrl += c; + newlen++; + } + + url = QString::fromUtf8(newUrl.c_str()); +} diff --git a/src/gui/qt/Url.hpp b/src/gui/qt/Url.hpp new file mode 100644 index 0000000000..2494433e90 --- /dev/null +++ b/src/gui/qt/Url.hpp @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef __URL_HPP__ +#define __URL_HPP__ + +#include <qstring.h> + +namespace Url +{ + void decode(QString &url); +} + +#endif + diff --git a/src/gui/qt/VolumeControl.cpp b/src/gui/qt/VolumeControl.cpp new file mode 100644 index 0000000000..aa32415950 --- /dev/null +++ b/src/gui/qt/VolumeControl.cpp @@ -0,0 +1,173 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <qevent.h> +#include <iostream> + + +#include "TransparentWidget.hpp" +#include "VolumeControl.hpp" + +#define SLIDER_IMAGE "slider.png" + +VolumeControl::VolumeControl (const QString &pixname, + QWidget *parent, + int minValue, + int maxValue) + : QLabel(parent) + , mMin(minValue) + , mMax(maxValue) + , mValue(minValue) + , mOrientation(VolumeControl::Horizontal) + , mSlider(new TransparentWidget(pixname, this)) + , mMaxPosition(100) +{ + resize(); +} + +VolumeControl::~VolumeControl() +{} + +void +VolumeControl::resize() +{ + QPixmap q(QPixmap::fromMimeSource(SLIDER_IMAGE)); + setPixmap(q); + if(q.hasAlpha()) { + setMask(*q.mask()); + } + + QWidget::resize(q.size()); + mMaxPosition = q.height() - mSlider->height(); +} + +void +VolumeControl::setOrientation(VolumeControl::Orientation orientation) +{ + mOrientation = orientation; +} + +void +VolumeControl::setMax(int value) +{ + if(value >= mMin) { + mMax = value; + } +} + +void +VolumeControl::setMin(int value) +{ + if(value <= mMax) { + mMin = value; + } +} + +void +VolumeControl::setValue(int value) +{ + if(value != mValue) { + if(value <= mMax && value >= mMin) { + mValue = value; + updateSlider(value); + emit valueUpdated(mValue); + } + } +} + +void +VolumeControl::mouseMoveEvent (QMouseEvent *e) { + if (mOrientation == VolumeControl::Vertical) { + // If the slider for the volume is vertical + int newpos = mSlider->y() + e->globalY() - mPos.y(); + + mPos = e->globalPos(); + if(newpos < 0) { + mPos.setY(mPos.y() - newpos); + newpos = 0; + } + + if(newpos > mMaxPosition) { + mPos.setY(mPos.y() - (newpos - mMaxPosition)); + newpos = mMaxPosition; + } + + mSlider->move(mSlider->x(), newpos); + updateValue(); + } + else { + mSlider->move(e->y() - mPos.x(), mSlider->y()); + } +} + +void +VolumeControl::updateValue() +{ + int value = (int)((float)offset() / mMaxPosition * (mMax - mMin)); + if(mValue != value) { + mValue = value; + emit valueUpdated(mValue); + } +} + + +void +VolumeControl::updateSlider(int value) +{ + if(mOrientation == VolumeControl::Vertical) { + mSlider->move(mSlider->x(), mMaxPosition - (int)((float)value / (mMax - mMin) * mMaxPosition)); + } + else { + mSlider->move(value / (mMax - mMin) * mMaxPosition, mSlider->y()); + } +} + +int +VolumeControl::offset() +{ + if(mOrientation == VolumeControl::Vertical) { + return mMaxPosition - mSlider->y(); + } + else { + return mSlider->x(); + } +} + +void +VolumeControl::mousePressEvent (QMouseEvent *e) +{ + mPos = e->globalPos(); + int newpos = e->pos().y() - (mSlider->height() / 2); + + mPos = e->globalPos(); + if(newpos < 0) { + mPos.setY(mPos.y() - newpos); + newpos = 0; + } + + if(newpos > mMaxPosition) { + mPos.setY(mPos.y() - (newpos - mMaxPosition)); + newpos = mMaxPosition; + } + + mSlider->move(mSlider->x(), newpos); + updateValue(); +} + +// EOF diff --git a/src/gui/qt/VolumeControl.hpp b/src/gui/qt/VolumeControl.hpp new file mode 100644 index 0000000000..0ca082afc6 --- /dev/null +++ b/src/gui/qt/VolumeControl.hpp @@ -0,0 +1,75 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __VOLUMECONTROL_HPP__ +#define __VOLUMECONTROL_HPP__ + +#include <qlabel.h> +#include "TransparentWidget.hpp" + +class VolumeControl : public QLabel +{ + Q_OBJECT + +public: + typedef enum {Vertical = 0, Horizontal} Orientation; + + VolumeControl(const QString &pixmap, + QWidget *parent = 0, + int minValue = 0, + int maxValue = 100); + ~VolumeControl(void); + + int getValue() + {return mValue;} + + int offset(); + int minY(); + int maxY(); + +signals: + void valueUpdated(int); + +public slots: + void updateValue(); + void setMin(int value); + void setMax(int value); + void setValue(int value); + void resize(); + void setOrientation(Orientation orientation); + +private: + void updateSlider(int value); + void mouseMoveEvent(QMouseEvent*); + void mousePressEvent(QMouseEvent*); + + + int mMin; + int mMax; + int mValue; + + VolumeControl::Orientation mOrientation; + QPoint mPos; + + TransparentWidget *mSlider; + int mMaxPosition; +}; + +#endif // __VOLUME_CONTROL_H__ diff --git a/src/gui/qt/globals.h b/src/gui/qt/globals.h new file mode 100644 index 0000000000..2cddbb7e95 --- /dev/null +++ b/src/gui/qt/globals.h @@ -0,0 +1,55 @@ +/** + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef SFLPHONE_GLOBAL_H +#define SFLPHONE_GLOBAL_H + +#define DEBUG + +#define NB_PHONELINES 6 +#define PROGNAME "SFLPhone" +#define VERSION "0.4.2" + +#define AUDIO_SECTION "Audio" +#define AUDIO_DEFAULT_DEVICE "Drivers.driverName" +#define AUDIO_CODEC1 "Codecs.codec1" +#define AUDIO_CODEC2 "Codecs.codec2" +#define AUDIO_CODEC3 "Codecs.codec3" +#define AUDIO_RINGTONE "Rings.ringChoice" + + +#define SIGNALISATION_SECTION "VoIPLink" +#define SIGNALISATION_FULL_NAME "SIP.fullName" +#define SIGNALISATION_USER_PART "SIP.userPart" +#define SIGNALISATION_AUTH_USER_NAME "SIP.username" +#define SIGNALISATION_PASSWORD "SIP.password" +#define SIGNALISATION_HOST_PART "SIP.hostPart" +#define SIGNALISATION_PROXY "SIP.proxy" +#define SIGNALISATION_AUTO_REGISTER "SIP.autoregister" +#define SIGNALISATION_PLAY_TONES "DTMF.playTones" +#define SIGNALISATION_PULSE_LENGTH "DTMF.pulseLength" +#define SIGNALISATION_SEND_DTMF_AS "DTMF.sendDTMFas" +#define SIGNALISATION_STUN_SERVER "STUN.STUNserver" +#define SIGNALISATION_USE_STUN "STUN.useStun" + +#define PREFERENCES_SECTION "Preferences" +#define PREFERENCES_THEME "Themes.skinChoice" + +#endif diff --git a/src/gui/qt/main.cpp b/src/gui/qt/main.cpp new file mode 100644 index 0000000000..3069b27639 --- /dev/null +++ b/src/gui/qt/main.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2004-2005 Savoir-Faire Linux inc. + * Author: Yan Morin <yan.morin@savoirfairelinux.com> + * Author: Jean-Philippe Barrette-LaPierre + * <jean-philippe.barrette-lapierre@savoirfairelinux.com> + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <iostream> +#include <stdexcept> +#include <qcolor.h> +#include <qsplashscreen.h> +#include <qstring.h> +#include <qtextcodec.h> +#include <qtimer.h> +#include <qtranslator.h> + +#include "PhoneLineManager.hpp" +#include "SFLPhoneApp.hpp" +#include "SFLPhoneWindow.hpp" +#include "TransparentWidget.hpp" + +int main(int argc, char **argv) +{ + SFLPhoneApp app(argc, argv); + + QSplashScreen *splash = new QSplashScreen(TransparentWidget::retreive("splash.png")); + splash->show(); + + // translation file for Qt + QTranslator qt(NULL); + qt.load( QString( "qt_" ) + QTextCodec::locale(), "." ); + app.installTranslator( &qt ); + + + QTranslator myapp(NULL); + myapp.load( QString( "sflphone-qt_" ) + QTextCodec::locale(), "." ); + app.installTranslator( &myapp ); + + SFLPhoneWindow* sfl = new SFLPhoneWindow(); + app.initConnections(sfl); +#ifndef QT3_SUPPORT + app.setMainWidget(sfl); +#endif + + app.launch(); + PhoneLineManager::instance().connect(); + //splash->finish(sfl); + //sfl->show(); + QObject::connect(&PhoneLineManager::instance(), SIGNAL(connected()), + splash, SLOT(hide())); + + // we connect this app to connected() signal, to handle argument + QObject::connect(&PhoneLineManager::instance(), SIGNAL(handleEventsSent()), &app, SLOT(handleArg())); + + + + // QTimer *timer = new QTimer(sfl); + // QObject::connect(timer, SIGNAL(timeout()), + // sfl, SLOT(show())); +// QObject::connect(timer, SIGNAL(timeout()), +// splash, SLOT(close())); + +// timer->start(1500, true); + + //delete splash; + + app.loadSkin(); + return app.exec(); +} -- GitLab