diff options
author | Tobias Markmann <tm@ayena.de> | 2012-02-26 14:32:39 (GMT) |
---|---|---|
committer | Tobias Markmann <tm@ayena.de> | 2012-11-11 16:38:00 (GMT) |
commit | 684559ff499077e33d3d5e4b9ecb39afa240d067 (patch) | |
tree | 7c0f03ddb4c73e1d2d2ddd54fe3f3b9640291e75 | |
parent | be6fd0b4b580d81bfe33975c28ee7a939d6c6723 (diff) | |
download | swift-contrib-684559ff499077e33d3d5e4b9ecb39afa240d067.zip swift-contrib-684559ff499077e33d3d5e4b9ecb39afa240d067.tar.bz2 |
Adding basic vCard edit/show support.
License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details.
67 files changed, 5282 insertions, 139 deletions
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index 50eee68..192946e 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -24,6 +24,7 @@ #include <Swift/Controllers/UIEvents/UIEventStream.h> #include <Swift/Controllers/UIEvents/RequestChatUIEvent.h> #include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h> +#include <Swift/Controllers/UIEvents/ShowProfileForRosterItemUIEvent.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> #include <Swiften/Avatars/AvatarManager.h> @@ -146,6 +147,7 @@ void MUCController::handleWindowOccupantSelectionChanged(ContactRosterItem* item if (muc_->getOccupant(item->getJID().getResource()).getRealJID()) { actions.push_back(ChatWindow::AddContact); } + actions.push_back(ChatWindow::ShowProfile); } chatWindow_->setAvailableOccupantActions(actions); } @@ -164,6 +166,7 @@ void MUCController::handleActionRequestedOnOccupant(ChatWindow::OccupantAction a case ChatWindow::MakeParticipant: muc_->changeOccupantRole(mucJID, MUCOccupant::Participant);break; case ChatWindow::MakeVisitor: muc_->changeOccupantRole(mucJID, MUCOccupant::Visitor);break; case ChatWindow::AddContact: if (occupant.getRealJID()) events_->send(boost::make_shared<RequestAddUserDialogUIEvent>(realJID, occupant.getNick()));break; + case ChatWindow::ShowProfile: events_->send(boost::make_shared<ShowProfileForRosterItemUIEvent>(mucJID));break; } } diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 1b0b595..de4f727 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -69,6 +69,7 @@ #include "Swift/Controllers/Storages/CertificateStorageTrustChecker.h" #include "Swiften/Network/NetworkFactories.h" #include <Swift/Controllers/ProfileController.h> +#include <Swift/Controllers/ShowProfileController.h> #include <Swift/Controllers/ContactEditController.h> #include <Swift/Controllers/XMPPURIController.h> #include "Swift/Controllers/AdHocManager.h" @@ -121,6 +122,7 @@ MainController::MainController( historyViewController_ = NULL; eventWindowController_ = NULL; profileController_ = NULL; + showProfileController_ = NULL; contactEditController_ = NULL; userSearchControllerChat_ = NULL; userSearchControllerAdd_ = NULL; @@ -225,6 +227,8 @@ void MainController::resetClient() { contactEditController_ = NULL; delete profileController_; profileController_ = NULL; + delete showProfileController_; + showProfileController_ = NULL; delete eventWindowController_; eventWindowController_ = NULL; delete chatsManager_; @@ -297,6 +301,7 @@ void MainController::handleConnected() { myStatusLooksOnline_ = true; if (freshLogin) { profileController_ = new ProfileController(client_->getVCardManager(), uiFactory_, uiEventStream_); + showProfileController_ = new ShowProfileController(client_->getVCardManager(), uiFactory_, uiEventStream_); srand(time(NULL)); int randomPort = 10000 + rand() % 10000; client_->getFileTransferManager()->startListeningOnPort(randomPort); diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h index 2e5bd05..efe092f 100644 --- a/Swift/Controllers/MainController.h +++ b/Swift/Controllers/MainController.h @@ -43,6 +43,7 @@ namespace Swift { class MUCController; class Notifier; class ProfileController; + class ShowProfileController; class ContactEditController; class TogglableNotifier; class PresenceNotifier; @@ -153,6 +154,7 @@ namespace Swift { FileTransferListController* fileTransferListController_; ChatsManager* chatsManager_; ProfileController* profileController_; + ShowProfileController* showProfileController_; ContactEditController* contactEditController_; JID jid_; JID boundJID_; diff --git a/Swift/Controllers/ProfileController.cpp b/Swift/Controllers/ProfileController.cpp index 101e283..e641988 100644 --- a/Swift/Controllers/ProfileController.cpp +++ b/Swift/Controllers/ProfileController.cpp @@ -37,6 +37,7 @@ void ProfileController::handleUIEvent(UIEvent::ref event) { if (!profileWindow) { profileWindow = profileWindowFactory->createProfileWindow(); + profileWindow->setEditable(true); profileWindow->onVCardChangeRequest.connect(boost::bind(&ProfileController::handleVCardChangeRequest, this, _1)); vcardManager->onOwnVCardChanged.connect(boost::bind(&ProfileController::handleOwnVCardChanged, this, _1)); } diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript index 7cd017b..954067e 100644 --- a/Swift/Controllers/SConscript +++ b/Swift/Controllers/SConscript @@ -30,6 +30,7 @@ if env["SCONS_STAGE"] == "build" : "Chat/UserSearchController.cpp", "MainController.cpp", "ProfileController.cpp", + "ShowProfileController.cpp", "ContactEditController.cpp", "FileTransfer/FileTransferController.cpp", "FileTransfer/FileTransferOverview.cpp", diff --git a/Swift/Controllers/ShowProfileController.cpp b/Swift/Controllers/ShowProfileController.cpp new file mode 100644 index 0000000..462ac42 --- /dev/null +++ b/Swift/Controllers/ShowProfileController.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "ShowProfileController.h" + +#include <boost/bind.hpp> + +#include <Swiften/Base/foreach.h> +#include <Swiften/VCards/VCardManager.h> + +#include <Swift/Controllers/UIEvents/ShowProfileForRosterItemUIEvent.h> +#include <Swift/Controllers/UIEvents/UIEventStream.h> +#include <Swift/Controllers/UIInterfaces/ProfileWindowFactory.h> + +namespace Swift { + +ShowProfileController::ShowProfileController(VCardManager* vcardManager, ProfileWindowFactory* profileWindowFactory, UIEventStream* uiEventStream) : vcardManager(vcardManager), profileWindowFactory(profileWindowFactory), uiEventStream(uiEventStream) { + uiEventStream->onUIEvent.connect(boost::bind(&ShowProfileController::handleUIEvent, this, _1)); + vcardManager->onVCardChanged.connect(boost::bind(&ShowProfileController::handleVCardChanged, this, _1, _2)); +} + +ShowProfileController::~ShowProfileController() { + typedef std::pair<JID, ProfileWindow*> JIDProfileWindowPair; + foreach(const JIDProfileWindowPair& jidWndPair, openedProfileWindows) { + jidWndPair.second->onWindowClosed.disconnect(boost::bind(&ShowProfileController::handleProfileWindowClosed, this, _1)); + delete jidWndPair.second; + } + + vcardManager->onVCardChanged.disconnect(boost::bind(&ShowProfileController::handleVCardChanged, this, _1, _2)); + uiEventStream->onUIEvent.disconnect(boost::bind(&ShowProfileController::handleUIEvent, this, _1)); +} + +void ShowProfileController::handleUIEvent(UIEvent::ref event) { + ShowProfileForRosterItemUIEvent::ref showProfileEvent; + if (!(showProfileEvent = boost::dynamic_pointer_cast<ShowProfileForRosterItemUIEvent>(event))) { + return; + } + + if (openedProfileWindows.find(showProfileEvent->getJID()) == openedProfileWindows.end()) { + ProfileWindow* newProfileWindow = profileWindowFactory->createProfileWindow(); + newProfileWindow->setJID(showProfileEvent->getJID()); + newProfileWindow->onWindowClosed.connect(boost::bind(&ShowProfileController::handleProfileWindowClosed, this, _1)); + openedProfileWindows[showProfileEvent->getJID()] = newProfileWindow; + VCard::ref vcard = vcardManager->getVCardAndRequestWhenNeeded(showProfileEvent->getJID()); + if (vcard) { + newProfileWindow->setVCard(vcard); + } else { + newProfileWindow->setProcessing(true); + } + newProfileWindow->show(); + } else { + openedProfileWindows[showProfileEvent->getJID()]->show(); + } +} + +void ShowProfileController::handleVCardChanged(const JID& jid, VCard::ref vcard) { + if (openedProfileWindows.find(jid) == openedProfileWindows.end()) { + return; + } + + ProfileWindow* profileWindow = openedProfileWindows[jid]; + profileWindow->setVCard(vcard); + profileWindow->setProcessing(false); + profileWindow->show(); +} + +void ShowProfileController::handleProfileWindowClosed(ProfileWindow* profileWindow) { + profileWindow->onWindowClosed.disconnect(boost::bind(&ShowProfileController::handleProfileWindowClosed, this, _1)); + JID profileJid; + for(std::map<JID, ProfileWindow*>::iterator i = openedProfileWindows.begin(); i != openedProfileWindows.end(); i++) { + if (i->second == profileWindow) { + profileJid = i->first; + break; + } + } + openedProfileWindows.erase(profileJid); + profileWindow->hide(); + delete profileWindow; +} + +} diff --git a/Swift/Controllers/ShowProfileController.h b/Swift/Controllers/ShowProfileController.h new file mode 100644 index 0000000..238946e --- /dev/null +++ b/Swift/Controllers/ShowProfileController.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/JID/JID.h> +#include <Swiften/Elements/VCard.h> + +#include <Swift/Controllers/UIEvents/UIEvent.h> + +namespace Swift { + class VCardManager; + class ProfileWindow; + class ProfileWindowFactory; + class UIEventStream; + + class ShowProfileController { + public: + ShowProfileController(VCardManager* vcardManager, ProfileWindowFactory* profileWindowFactory, UIEventStream* uiEventStream); + ~ShowProfileController(); + + private: + void handleUIEvent(UIEvent::ref event); + void handleVCardChanged(const JID&, VCard::ref); + void handleProfileWindowClosed(ProfileWindow* profileWindow); + + private: + VCardManager* vcardManager; + ProfileWindowFactory* profileWindowFactory; + UIEventStream* uiEventStream; + std::map<JID, ProfileWindow*> openedProfileWindows; + }; +} diff --git a/Swift/Controllers/UIEvents/ShowProfileForRosterItemUIEvent.h b/Swift/Controllers/UIEvents/ShowProfileForRosterItemUIEvent.h new file mode 100644 index 0000000..4941501 --- /dev/null +++ b/Swift/Controllers/UIEvents/ShowProfileForRosterItemUIEvent.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include "Swiften/JID/JID.h" +#include "Swift/Controllers/UIEvents/UIEvent.h" + +namespace Swift { + +class ShowProfileForRosterItemUIEvent : public UIEvent { + public: + typedef boost::shared_ptr<ShowProfileForRosterItemUIEvent> ref; + public: + ShowProfileForRosterItemUIEvent(const JID& jid) : jid_(jid) {} + virtual ~ShowProfileForRosterItemUIEvent() {} + JID getJID() {return jid_;} + private: + JID jid_; +}; + +} diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index 5db1a54..2a2078c 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -34,7 +34,7 @@ namespace Swift { enum AckState {Pending, Received, Failed}; enum ReceiptState {ReceiptRequested, ReceiptReceived}; enum Tristate {Yes, No, Maybe}; - enum OccupantAction {Kick, Ban, MakeModerator, MakeParticipant, MakeVisitor, AddContact}; + enum OccupantAction {Kick, Ban, MakeModerator, MakeParticipant, MakeVisitor, AddContact, ShowProfile}; enum RoomAction {ChangeSubject, Configure, Affiliations, Destroy, Invite}; enum FileTransferState {WaitingForAccept, Negotiating, Transferring, Canceled, Finished, FTFailed}; enum WhiteboardSessionState {WhiteboardAccepted, WhiteboardTerminated, WhiteboardRejected}; diff --git a/Swift/Controllers/UIInterfaces/ProfileWindow.h b/Swift/Controllers/UIInterfaces/ProfileWindow.h index 5d5c754..90d8584 100644 --- a/Swift/Controllers/UIInterfaces/ProfileWindow.h +++ b/Swift/Controllers/UIInterfaces/ProfileWindow.h @@ -12,19 +12,24 @@ #include <Swiften/Elements/VCard.h> namespace Swift { + class JID; + class ProfileWindow { public: virtual ~ProfileWindow() {}; + virtual void setJID(const JID& jid) = 0; virtual void setVCard(VCard::ref vcard) = 0; virtual void setEnabled(bool b) = 0; virtual void setProcessing(bool b) = 0; virtual void setError(const std::string&) = 0; + virtual void setEditable(bool b) = 0; virtual void show() = 0; virtual void hide() = 0; boost::signal<void (VCard::ref)> onVCardChangeRequest; + boost::signal<void (ProfileWindow*)> onWindowClosed; }; } diff --git a/Swift/QtUI/QtAvatarWidget.cpp b/Swift/QtUI/QtAvatarWidget.cpp index f0bdf3c..ae9559a 100644 --- a/Swift/QtUI/QtAvatarWidget.cpp +++ b/Swift/QtUI/QtAvatarWidget.cpp @@ -68,6 +68,9 @@ void QtAvatarWidget::setAvatar(const ByteArray& data, const std::string& type) { } void QtAvatarWidget::mousePressEvent(QMouseEvent* event) { + if (!editable) { + return; + } QMenu menu; QAction* selectPicture = new QAction(tr("Select picture ..."), this); diff --git a/Swift/QtUI/QtAvatarWidget.h b/Swift/QtUI/QtAvatarWidget.h index 8830d82..f4ac4cf 100644 --- a/Swift/QtUI/QtAvatarWidget.h +++ b/Swift/QtUI/QtAvatarWidget.h @@ -15,6 +15,7 @@ class QLabel; namespace Swift { class QtAvatarWidget : public QWidget { Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) public: QtAvatarWidget(QWidget* parent); @@ -28,9 +29,18 @@ namespace Swift { return type; } + void setEditable(bool b) { + editable = b; + } + + bool isEditable() const { + return editable; + } + void mousePressEvent(QMouseEvent* event); private: + bool editable; ByteArray data; std::string type; QLabel* label; diff --git a/Swift/QtUI/QtProfileWindow.cpp b/Swift/QtUI/QtProfileWindow.cpp index 0faa78f..558d685 100644 --- a/Swift/QtUI/QtProfileWindow.cpp +++ b/Swift/QtUI/QtProfileWindow.cpp @@ -1,100 +1,76 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. */ #include "QtProfileWindow.h" +#include "ui_QtProfileWindow.h" -#include <QImage> -#include <QPixmap> -#include <QSizePolicy> -#include <QGridLayout> -#include <QLabel> -#include <QLineEdit> -#include <QPushButton> +#include <QCloseEvent> #include <QMovie> +#include <QShortcut> #include "QtSwiftUtil.h" -#include "QtAvatarWidget.h" namespace Swift { -QtProfileWindow::QtProfileWindow() { - setWindowTitle(tr("Edit Profile")); - - QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); - sizePolicy.setHorizontalStretch(0); - sizePolicy.setVerticalStretch(0); - sizePolicy.setHeightForWidth(this->sizePolicy().hasHeightForWidth()); - setSizePolicy(sizePolicy); - - QVBoxLayout* layout = new QVBoxLayout(this); - layout->setContentsMargins(10, 10, 10, 10); - - QHBoxLayout* topLayout = new QHBoxLayout(); - - avatar = new QtAvatarWidget(this); - topLayout->addWidget(avatar); - - QVBoxLayout* fieldsLayout = new QVBoxLayout(); - - QHBoxLayout* horizontalLayout_2 = new QHBoxLayout(); - nicknameLabel = new QLabel(tr("Nickname:"), this); - horizontalLayout_2->addWidget(nicknameLabel); - nickname = new QLineEdit(this); - horizontalLayout_2->addWidget(nickname); - - fieldsLayout->addLayout(horizontalLayout_2); - - errorLabel = new QLabel(this); - errorLabel->setAlignment(Qt::AlignHCenter); - fieldsLayout->addWidget(errorLabel); - - fieldsLayout->addItem(new QSpacerItem(198, 17, QSizePolicy::Minimum, QSizePolicy::Expanding)); - topLayout->addLayout(fieldsLayout); - - layout->addLayout(topLayout); - - QHBoxLayout* horizontalLayout = new QHBoxLayout(); - horizontalLayout->setContentsMargins(0, 0, 0, 0); - horizontalLayout->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); - - throbberLabel = new QLabel(this); - throbberLabel->setMovie(new QMovie(":/icons/throbber.gif", QByteArray(), this)); - horizontalLayout->addWidget(throbberLabel); - - saveButton = new QPushButton(tr("Save"), this); - saveButton->setDefault( true ); - connect(saveButton, SIGNAL(clicked()), SLOT(handleSave())); - horizontalLayout->addWidget(saveButton); +QtProfileWindow::QtProfileWindow(QWidget* parent) : + QWidget(parent), + ui(new Ui::QtProfileWindow) { + ui->setupUi(this); + new QShortcut(QKeySequence::Close, this, SLOT(close())); + ui->throbberLabel->setMovie(new QMovie(":/icons/throbber.gif", QByteArray(), this)); + connect(ui->savePushButton, SIGNAL(clicked()), SLOT(handleSave())); + setEditable(false); +} - fieldsLayout->addLayout(horizontalLayout); +QtProfileWindow::~QtProfileWindow() { + delete ui; +} - resize(360, 120); +void QtProfileWindow::setJID(const JID& jid) { + this->jid = jid; + updateTitle(); } -void QtProfileWindow::setVCard(Swift::VCard::ref vcard) { - this->vcard = vcard; - nickname->setText(P2QSTRING(vcard->getNickname())); - avatar->setAvatar(vcard->getPhoto(), vcard->getPhotoType()); +void QtProfileWindow::setVCard(VCard::ref vcard) { + ui->vcard->setVCard(vcard); } void QtProfileWindow::setEnabled(bool b) { - nickname->setEnabled(b); - nicknameLabel->setEnabled(b); - avatar->setEnabled(b); - saveButton->setEnabled(b); + ui->vcard->setEnabled(b); + ui->savePushButton->setEnabled(b); +} + +void QtProfileWindow::setEditable(bool b) { + if (b) { + ui->savePushButton->show(); + ui->vcard->setEditable(true); + } else { + ui->savePushButton->hide(); + ui->vcard->setEditable(false); + } + updateTitle(); } void QtProfileWindow::setProcessing(bool processing) { if (processing) { - throbberLabel->movie()->start(); - throbberLabel->show(); + ui->throbberLabel->movie()->start(); + ui->throbberLabel->show(); } else { - throbberLabel->hide(); - throbberLabel->movie()->stop(); + ui->throbberLabel->hide(); + ui->throbberLabel->movie()->stop(); + } +} + +void QtProfileWindow::setError(const std::string& error) { + if (!error.empty()) { + ui->errorLabel->setText("<font color='red'>" + P2QSTRING(error) + "</font>"); + } + else { + ui->errorLabel->setText(""); } } @@ -103,31 +79,30 @@ void QtProfileWindow::show() { QWidget::activateWindow(); } -void QtProfileWindow::hideEvent(QHideEvent* event) { - QWidget::hideEvent(event); -} - void QtProfileWindow::hide() { QWidget::hide(); } -void QtProfileWindow::handleSave() { - assert(vcard); - vcard->setNickname(Q2PSTRING(nickname->text())); - vcard->setPhoto(avatar->getAvatarData()); - vcard->setPhotoType(avatar->getAvatarType()); - onVCardChangeRequest(vcard); -} - -void QtProfileWindow::setError(const std::string& error) { - if (!error.empty()) { - errorLabel->setText("<font color='red'>" + P2QSTRING(error) + "</font>"); +void QtProfileWindow::updateTitle() { + QString jidString; + if (jid.isValid()) { + jidString = QString(" ( %1 )").arg(P2QSTRING(jid.toString())); } - else { - errorLabel->setText(""); + + if (ui->vcard->isEditable()) { + setWindowTitle(tr("Edit Profile") + jidString); + } else { + setWindowTitle(tr("Show Profile") + jidString); } } +void QtProfileWindow::closeEvent(QCloseEvent* event) { + event->accept(); + onWindowClosed(this); +} +void QtProfileWindow::handleSave() { + onVCardChangeRequest(ui->vcard->getVCard()); +} } diff --git a/Swift/QtUI/QtProfileWindow.h b/Swift/QtUI/QtProfileWindow.h index edb9cce..29a832d 100644 --- a/Swift/QtUI/QtProfileWindow.h +++ b/Swift/QtUI/QtProfileWindow.h @@ -1,48 +1,51 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. */ #pragma once -#include <QWidget> +#include <Swiften/JID/JID.h> #include <Swift/Controllers/UIInterfaces/ProfileWindow.h> -class QLabel; -class QLineEdit; -class QHBoxLayout; -class QPushButton; +#include <QWidget> + +namespace Ui { + class QtProfileWindow; +} namespace Swift { - class QtAvatarWidget; - - class QtProfileWindow : public QWidget, public ProfileWindow { - Q_OBJECT - public: - QtProfileWindow(); - - void setVCard(Swift::VCard::ref); - void setEnabled(bool); - void setProcessing(bool); - virtual void setError(const std::string&); - void show(); - void hide(); - - void hideEvent (QHideEvent* event); - - private slots: - void handleSave(); - - private: - VCard::ref vcard; - QtAvatarWidget* avatar; - QLabel* nicknameLabel; - QLineEdit* nickname; - QLabel* throbberLabel; - QLabel* errorLabel; - QHBoxLayout* horizontalLayout; - QPushButton* saveButton; - }; + +class QtProfileWindow : public QWidget, public ProfileWindow { + Q_OBJECT + + public: + explicit QtProfileWindow(QWidget* parent = 0); + virtual ~QtProfileWindow(); + + virtual void setJID(const JID& jid); + virtual void setVCard(VCard::ref vcard); + + virtual void setEnabled(bool b); + virtual void setProcessing(bool processing); + virtual void setError(const std::string& error); + virtual void setEditable(bool b); + + virtual void show(); + virtual void hide(); + + private: + void updateTitle(); + virtual void closeEvent(QCloseEvent* event); + + private slots: + void handleSave(); + + private: + Ui::QtProfileWindow* ui; + JID jid; +}; + } diff --git a/Swift/QtUI/QtProfileWindow.ui b/Swift/QtUI/QtProfileWindow.ui new file mode 100644 index 0000000..68a36da --- /dev/null +++ b/Swift/QtUI/QtProfileWindow.ui @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtProfileWindow</class> + <widget class="QWidget" name="QtProfileWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>334</width> + <height>197</height> + </rect> + </property> + <property name="windowTitle"> + <string>Edit Profile</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" stretch="1,0"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="Swift::QtVCardWidget" name="vcard" native="true"/> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="errorLabel"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="throbberLabel"> + <property name="text"> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="textInteractionFlags"> + <set>Qt::NoTextInteraction</set> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="savePushButton"> + <property name="text"> + <string>Save</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Swift::QtVCardWidget</class> + <extends>QWidget</extends> + <header>Swift/QtUI/QtVCardWidget/QtVCardWidget.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtSwiftUtil.h b/Swift/QtUI/QtSwiftUtil.h index 2d0f970..c903af1 100644 --- a/Swift/QtUI/QtSwiftUtil.h +++ b/Swift/QtUI/QtSwiftUtil.h @@ -9,4 +9,6 @@ #define P2QSTRING(a) QString::fromUtf8(a.c_str()) #define Q2PSTRING(a) std::string(a.toUtf8()) +#include <boost/date_time/posix_time/posix_time.hpp> + #define B2QDATE(a) QDateTime::fromTime_t((a - boost::posix_time::from_time_t(0)).total_seconds()) diff --git a/Swift/QtUI/QtVCardWidget/QtResizableLineEdit.cpp b/Swift/QtUI/QtVCardWidget/QtResizableLineEdit.cpp new file mode 100644 index 0000000..d4357cb --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtResizableLineEdit.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtResizableLineEdit.h" + +#include <QDebug> + +namespace Swift { + +QtResizableLineEdit::QtResizableLineEdit(QWidget* parent) : + QLineEdit(parent) { + connect(this, SIGNAL(textChanged(QString)), SLOT(textChanged(QString))); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); +} + +QtResizableLineEdit::~QtResizableLineEdit() { +} + +bool QtResizableLineEdit::isEditable() const { + return editable; +} +void QtResizableLineEdit::setEditable(const bool editable) { + this->editable = editable; + if (editable) { + setReadOnly(false); + } else { + setReadOnly(true); + } +} + + +QSize QtResizableLineEdit::sizeHint() const { + int w = fontMetrics().boundingRect(text().isEmpty() ? placeholderText() : text()).width() + 10; + return QSize(w, height()); +} + +void QtResizableLineEdit::textChanged(QString) { + updateGeometry(); +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtResizableLineEdit.h b/Swift/QtUI/QtVCardWidget/QtResizableLineEdit.h new file mode 100644 index 0000000..9022d38 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtResizableLineEdit.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QLineEdit> + +namespace Swift { + + class QtResizableLineEdit : public QLineEdit { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + + public: + explicit QtResizableLineEdit(QWidget* parent = 0); + ~QtResizableLineEdit(); + + bool isEditable() const; + void setEditable(const bool); + + virtual QSize sizeHint() const; + + private slots: + void textChanged(QString); + + private: + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardAddressField.cpp b/Swift/QtUI/QtVCardWidget/QtVCardAddressField.cpp new file mode 100644 index 0000000..c1a08f1 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardAddressField.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardAddressField.h" +#include "ui_QtVCardAddressField.h" + +#define GETTER_SETTER_CHECKBOX_IMPL( METHOD_NAME, UI_NAME ) \ + void QtVCardAddressField::set##METHOD_NAME(const bool METHOD_NAME) { \ + ui->checkBox##UI_NAME->setChecked(METHOD_NAME); \ + } \ + \ + bool QtVCardAddressField::get##METHOD_NAME() const { \ + return ui->checkBox##UI_NAME->checkState() == Qt::Checked; \ + } + +#define GETTER_SETTER_LINEEDIT_IMPL( METHOD_NAME, UI_NAME ) \ + void QtVCardAddressField::set##METHOD_NAME(const QString METHOD_NAME) { \ + ui->lineEdit##UI_NAME->setText(METHOD_NAME); \ + } \ + \ + QString QtVCardAddressField::get##METHOD_NAME() const { \ + return ui->lineEdit##UI_NAME->text(); \ + } + +namespace Swift { + +QtVCardAddressField::QtVCardAddressField(QWidget* parent, bool editable) : + QWidget(parent), + ui(new Ui::QtVCardAddressField) { + ui->setupUi(this); + setEditable(editable); +} + +QtVCardAddressField::~QtVCardAddressField() { + delete ui; +} + +bool QtVCardAddressField::isEditable() const { + return editable; +} + +void QtVCardAddressField::setEditable(bool editable) { + this->editable = editable; + QList<QCheckBox*> allCheckBoxes = findChildren<QCheckBox*>(); + foreach(QCheckBox* checkbox, allCheckBoxes) { + if (editable) { + checkbox->setEnabled(true); + } else { + checkbox->setEnabled(false); + } + } + + QList<QtResizableLineEdit*> allLineEdits = findChildren<QtResizableLineEdit*>(); + foreach(QtResizableLineEdit* lineEdit, allLineEdits) { + if (editable) { + lineEdit->show(); + lineEdit->setEditable(true); + } else { + lineEdit->setEditable(false); + if (lineEdit->text().isEmpty()) { + lineEdit->hide(); + } else { + lineEdit->show(); + } + } + } + + if (editable) { + ui->comboBoxDOM_INTL->setEnabled(true); + } else { + ui->comboBoxDOM_INTL->setEnabled(false); + } +} + +bool QtVCardAddressField::isEmpty() const { + return false; +} + +GETTER_SETTER_CHECKBOX_IMPL(Home, HOME) +GETTER_SETTER_CHECKBOX_IMPL(Work, WORK) +GETTER_SETTER_CHECKBOX_IMPL(Postal, POSTAL) +GETTER_SETTER_CHECKBOX_IMPL(Parcel, PARCEL) +GETTER_SETTER_CHECKBOX_IMPL(Preferred, PREF) + +void QtVCardAddressField::setDeliveryType(DeliveryType type) { + ui->comboBoxDOM_INTL->setCurrentIndex(type); +} + +QtVCardAddressField::DeliveryType QtVCardAddressField::getDeliveryType() const { + return ui->comboBoxDOM_INTL->currentIndex() == 1 ? InternationalDelivery : DomesticDelivery; +} + +GETTER_SETTER_LINEEDIT_IMPL(POBox, POBOX) +GETTER_SETTER_LINEEDIT_IMPL(AddressExtension, EXTADD) +GETTER_SETTER_LINEEDIT_IMPL(Street, STREET) +GETTER_SETTER_LINEEDIT_IMPL(Locality, LOCALITY) +GETTER_SETTER_LINEEDIT_IMPL(Region, REGION) +GETTER_SETTER_LINEEDIT_IMPL(PostalCode, PCODE) +GETTER_SETTER_LINEEDIT_IMPL(Country, CTRY) + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardAddressField.h b/Swift/QtUI/QtVCardWidget/QtVCardAddressField.h new file mode 100644 index 0000000..9f2c83b --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardAddressField.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include "QtVCardFieldInfo.h" + +namespace Swift { + + namespace Ui { + class QtVCardAddressField; + } + + class QtVCardAddressField : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_PROPERTY(bool empty READ isEmpty) + + public : + class FieldInfo : public QtVCardFieldInfo { + public: + virtual ~FieldInfo() { + } + virtual QString getMenuName() const { + return tr("Address"); + } + virtual int getAllowedInstances() const { + return UNLIMITED_INSTANCES; + } + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const { + return new QtVCardAddressField(parent, editable); + } + virtual bool testInstance(QWidget* widget) const { + return dynamic_cast<QtVCardAddressField*>(widget) != 0; + } + }; + + public: + enum DeliveryType { + DomesticDelivery = 0, + InternationalDelivery + }; + + public: + explicit QtVCardAddressField(QWidget* parent = 0, bool editable = false); + ~QtVCardAddressField(); + + bool isEditable() const; + void setEditable(bool); + + bool isEmpty() const; + + void setHome(const bool); + bool getHome() const; + + void setWork(const bool); + bool getWork() const; + + void setPostal(const bool); + bool getPostal() const; + + void setParcel(const bool); + bool getParcel() const; + + void setPreferred(const bool); + bool getPreferred() const; + + void setPOBox(const QString); + QString getPOBox() const; + + void setDeliveryType(DeliveryType type); + DeliveryType getDeliveryType() const; + + void setAddressExtension(const QString); + QString getAddressExtension() const; + + void setStreet(const QString); + QString getStreet() const; + + void setLocality(const QString); + QString getLocality() const; + + void setRegion(const QString); + QString getRegion() const; + + void setPostalCode(const QString); + QString getPostalCode() const; + + void setCountry(const QString); + QString getCountry() const; + + private slots: + + private: + Ui::QtVCardAddressField* ui; + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardAddressField.ui b/Swift/QtUI/QtVCardWidget/QtVCardAddressField.ui new file mode 100644 index 0000000..f5dffc8 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardAddressField.ui @@ -0,0 +1,229 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Swift::QtVCardAddressField</class> + <widget class="QWidget" name="Swift::QtVCardAddressField"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>524</width> + <height>120</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QGridLayout" name="gridLayout"> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>2</number> + </property> + <item row="0" column="1"> + <widget class="Swift::QtResizableLineEdit" name="lineEditSTREET"> + <property name="toolTip"> + <string>Street</string> + </property> + <property name="placeholderText"> + <string>Street</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="Swift::QtResizableLineEdit" name="lineEditREGION"> + <property name="toolTip"> + <string>Region</string> + </property> + <property name="placeholderText"> + <string>Region</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="Swift::QtResizableLineEdit" name="lineEditCTRY"> + <property name="toolTip"> + <string>Country</string> + </property> + <property name="placeholderText"> + <string>Country</string> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="Swift::QtResizableLineEdit" name="lineEditPCODE"> + <property name="toolTip"> + <string>Postal Code</string> + </property> + <property name="placeholderText"> + <string>Postal Code</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="Swift::QtResizableLineEdit" name="lineEditLOCALITY"> + <property name="toolTip"> + <string>City</string> + </property> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string>City</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="Swift::QtResizableLineEdit" name="lineEditEXTADD"> + <property name="toolTip"> + <string>Address Extension</string> + </property> + <property name="placeholderText"> + <string>Address Extension</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="Swift::QtResizableLineEdit" name="lineEditPOBOX"> + <property name="toolTip"> + <string>PO Box</string> + </property> + <property name="placeholderText"> + <string>PO Box</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QGridLayout" name="gridLayout_2"> + <property name="margin"> + <number>0</number> + </property> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBoxPREF"> + <property name="toolTip"> + <string>Preferred</string> + </property> + <property name="text"> + <string>Preferred</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QCheckBox" name="checkBoxHOME"> + <property name="toolTip"> + <string>Home</string> + </property> + <property name="text"> + <string>Home</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QCheckBox" name="checkBoxWORK"> + <property name="toolTip"> + <string>Work</string> + </property> + <property name="text"> + <string>Work</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QCheckBox" name="checkBoxPOSTAL"> + <property name="toolTip"> + <string>Postal</string> + </property> + <property name="text"> + <string>Postal</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QCheckBox" name="checkBoxPARCEL"> + <property name="toolTip"> + <string>Parcel</string> + </property> + <property name="text"> + <string>Parcel</string> + </property> + </widget> + </item> + <item row="2" column="0" colspan="3"> + <widget class="QComboBox" name="comboBoxDOM_INTL"> + <property name="toolTip"> + <string>Delivery Type</string> + </property> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToMinimumContentsLength</enum> + </property> + <item> + <property name="text"> + <string>Domestic Delivery</string> + </property> + </item> + <item> + <property name="text"> + <string>International Delivery</string> + </property> + </item> + </widget> + </item> + <item row="3" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Swift::QtResizableLineEdit</class> + <extends>QLineEdit</extends> + <header>QtResizableLineEdit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardAddressLabelField.cpp b/Swift/QtUI/QtVCardWidget/QtVCardAddressLabelField.cpp new file mode 100644 index 0000000..79e4440 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardAddressLabelField.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardAddressLabelField.h" +#include "ui_QtVCardAddressLabelField.h" + +#define GETTER_SETTER_CHECKBOX_IMPL( METHOD_NAME, UI_NAME ) \ + void QtVCardAddressLabelField::set##METHOD_NAME(const bool METHOD_NAME) { \ + ui->checkBox##UI_NAME->setChecked(METHOD_NAME); \ + } \ + \ + bool QtVCardAddressLabelField::get##METHOD_NAME() const { \ + return ui->checkBox##UI_NAME->checkState() == Qt::Checked; \ + } + +namespace Swift { + +QtVCardAddressLabelField::QtVCardAddressLabelField(QWidget* parent, bool editable) : + QWidget(parent), + ui(new Ui::QtVCardAddressLabelField) { + ui->setupUi(this); + setEditable(editable); +} + +QtVCardAddressLabelField::~QtVCardAddressLabelField() { + delete ui; +} + +bool QtVCardAddressLabelField::isEditable() const { + return editable; +} + +void QtVCardAddressLabelField::setEditable(bool editable) { + this->editable = editable; + ui->plainTextEditLINES->setReadOnly(!editable); +} + +bool QtVCardAddressLabelField::isEmpty() const { + return false; +} + +GETTER_SETTER_CHECKBOX_IMPL(Home, HOME) +GETTER_SETTER_CHECKBOX_IMPL(Work, WORK) +GETTER_SETTER_CHECKBOX_IMPL(Postal, POSTAL) +GETTER_SETTER_CHECKBOX_IMPL(Parcel, PARCEL) +GETTER_SETTER_CHECKBOX_IMPL(Preferred, PREF) + +void QtVCardAddressLabelField::setDeliveryType(DeliveryType type) { + ui->comboBoxDOM_INTL->setCurrentIndex(type); +} + +QtVCardAddressLabelField::DeliveryType QtVCardAddressLabelField::getDeliveryType() const { + return ui->comboBoxDOM_INTL->currentIndex() == 1 ? InternationalDelivery : DomesticDelivery; +} + +void QtVCardAddressLabelField::setLines(const QString& lines) { + ui->plainTextEditLINES->setPlainText(lines); +} + +QString QtVCardAddressLabelField::getLines() const { + return ui->plainTextEditLINES->toPlainText(); +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardAddressLabelField.h b/Swift/QtUI/QtVCardWidget/QtVCardAddressLabelField.h new file mode 100644 index 0000000..868fbce --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardAddressLabelField.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include "QtVCardFieldInfo.h" + +namespace Swift { + + namespace Ui { + class QtVCardAddressLabelField; + } + + class QtVCardAddressLabelField : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_PROPERTY(bool empty READ isEmpty) + + public : + class FieldInfo : public QtVCardFieldInfo { + public: + virtual ~FieldInfo() { + } + virtual QString getMenuName() const { + return tr("Address Label"); + } + virtual int getAllowedInstances() const { + return UNLIMITED_INSTANCES; + } + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const { + return new QtVCardAddressLabelField(parent, editable); + } + virtual bool testInstance(QWidget* widget) const { + return dynamic_cast<QtVCardAddressLabelField*>(widget) != 0; + } + }; + + public: + enum DeliveryType { + DomesticDelivery = 0, + InternationalDelivery + }; + + public: + explicit QtVCardAddressLabelField(QWidget* parent = 0, bool editable = false); + ~QtVCardAddressLabelField(); + + bool isEditable() const; + void setEditable(bool); + + bool isEmpty() const; + + void setHome(const bool); + bool getHome() const; + + void setWork(const bool); + bool getWork() const; + + void setPostal(const bool); + bool getPostal() const; + + void setParcel(const bool); + bool getParcel() const; + + void setPreferred(const bool); + bool getPreferred() const; + + void setPOBox(const QString); + QString getPOBox() const; + + void setDeliveryType(DeliveryType type); + DeliveryType getDeliveryType() const; + + void setLines(const QString&); + QString getLines() const; + + private slots: + + private: + Ui::QtVCardAddressLabelField* ui; + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardAddressLabelField.ui b/Swift/QtUI/QtVCardWidget/QtVCardAddressLabelField.ui new file mode 100644 index 0000000..dc1de27 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardAddressLabelField.ui @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Swift::QtVCardAddressLabelField</class> + <widget class="QWidget" name="Swift::QtVCardAddressLabelField"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>614</width> + <height>80</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QPlainTextEdit" name="plainTextEditLINES"> + <property name="toolTip"> + <string>Address Label</string> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="lineWrapMode"> + <enum>QPlainTextEdit::NoWrap</enum> + </property> + <property name="backgroundVisible"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>146</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBoxPREF"> + <property name="toolTip"> + <string>Preferred</string> + </property> + <property name="text"> + <string>Preferred</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QCheckBox" name="checkBoxHOME"> + <property name="toolTip"> + <string>Home</string> + </property> + <property name="text"> + <string>Home</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QCheckBox" name="checkBoxWORK"> + <property name="toolTip"> + <string>Work</string> + </property> + <property name="text"> + <string>Work</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QCheckBox" name="checkBoxPOSTAL"> + <property name="toolTip"> + <string>Postal</string> + </property> + <property name="text"> + <string>Postal</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QCheckBox" name="checkBoxPARCEL"> + <property name="toolTip"> + <string>Parcel</string> + </property> + <property name="text"> + <string>Parcel</string> + </property> + </widget> + </item> + <item row="2" column="0" colspan="3"> + <widget class="QComboBox" name="comboBoxDOM_INTL"> + <property name="toolTip"> + <string>Delivery Type</string> + </property> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToMinimumContentsLength</enum> + </property> + <item> + <property name="text"> + <string>Domestic Delivery</string> + </property> + </item> + <item> + <property name="text"> + <string>International Delivery</string> + </property> + </item> + </widget> + </item> + <item row="3" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardBirthdayField.cpp b/Swift/QtUI/QtVCardWidget/QtVCardBirthdayField.cpp new file mode 100644 index 0000000..3cad247 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardBirthdayField.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardBirthdayField.h" +#include "ui_QtVCardBirthdayField.h" + +#include <QLayout> + +namespace Swift { + +QtVCardBirthdayField::QtVCardBirthdayField(QWidget* parent, bool editable) : + QWidget(parent), + ui(new Ui::QtVCardBirthdayField) { + ui->setupUi(this); + connect(ui->deleteField, SIGNAL(clicked()), SLOT(onDeleteFieldPressed())); + setEditable(editable); +} + +QtVCardBirthdayField::~QtVCardBirthdayField() { + delete ui; +} + +bool QtVCardBirthdayField::isEditable() const { + return editable; +} + +void QtVCardBirthdayField::setEditable(bool editable) { + if (editable) { + ui->labelBDAY->hide(); + ui->dateEditBDAY->show(); + ui->deleteField->show(); + } else { + ui->dateEditBDAY->hide(); + ui->deleteField->hide(); + ui->labelBDAY->show(); + } + this->editable = editable; +} + +bool QtVCardBirthdayField::isEmpty() const { + return false; +} + +void QtVCardBirthdayField::setBirthday(const QDate& date) { + ui->labelBDAY->setText(date.toString()); + ui->dateEditBDAY->setDate(date); +} + +QDate QtVCardBirthdayField::getBirthday() const { + return ui->dateEditBDAY->date(); +} + +void QtVCardBirthdayField::onDateChanged(QDate date) { + ui->labelBDAY->setText(date.toString()); +} + +void QtVCardBirthdayField::onDeleteFieldPressed() { + delete this; +} + +} + diff --git a/Swift/QtUI/QtVCardWidget/QtVCardBirthdayField.h b/Swift/QtUI/QtVCardWidget/QtVCardBirthdayField.h new file mode 100644 index 0000000..28197c0 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardBirthdayField.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> +#include <QDate> + +#include "QtVCardFieldInfo.h" + +namespace Swift { + + namespace Ui { + class QtVCardBirthdayField; + } + + class QtVCardBirthdayField : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_PROPERTY(bool empty READ isEmpty) + + public : + class FieldInfo : public QtVCardFieldInfo { + public: + virtual ~FieldInfo() { + } + virtual QString getMenuName() const { + return tr("Birthday"); + } + virtual int getAllowedInstances() const { + return 1; + } + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const { + return new QtVCardBirthdayField(parent, editable); + } + virtual bool testInstance(QWidget* widget) const { + return dynamic_cast<QtVCardBirthdayField*>(widget) != 0; + } + }; + + public: + explicit QtVCardBirthdayField(QWidget* parent = 0, bool editable = false); + virtual ~QtVCardBirthdayField(); + + bool isEditable() const; + void setEditable(bool); + + bool isEmpty() const; + + void setBirthday(const QDate& date); + QDate getBirthday() const; + + private slots: + void onDateChanged(QDate date); + void onDeleteFieldPressed(); + + private: + Ui::QtVCardBirthdayField* ui; + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardBirthdayField.ui b/Swift/QtUI/QtVCardWidget/QtVCardBirthdayField.ui new file mode 100644 index 0000000..bb6ddd4 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardBirthdayField.ui @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Swift::QtVCardBirthdayField</class> + <widget class="QWidget" name="Swift::QtVCardBirthdayField"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>392</width> + <height>38</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="labelBDAY"> + <property name="toolTip"> + <string>Birthday</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QDateEdit" name="dateEditBDAY"> + <property name="toolTip"> + <string>Birthday</string> + </property> + <property name="displayFormat"> + <string>dd.MM.yyyy</string> + </property> + <property name="calendarPopup"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="deleteField"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>X</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardDescriptionField.cpp b/Swift/QtUI/QtVCardWidget/QtVCardDescriptionField.cpp new file mode 100644 index 0000000..c86d72e --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardDescriptionField.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardDescriptionField.h" +#include "ui_QtVCardDescriptionField.h" + +namespace Swift { + +QtVCardDescriptionField::QtVCardDescriptionField(QWidget* parent, bool editable) : + QWidget(parent), + ui(new Ui::QtVCardDescriptionField) { + ui->setupUi(this); + setEditable(editable); +} + +QtVCardDescriptionField::~QtVCardDescriptionField() { + delete ui; +} + +bool QtVCardDescriptionField::isEditable() const { + return editable; +} + +void QtVCardDescriptionField::setEditable(bool editable) { + this->editable = editable; + ui->plainTextEditDESC->setReadOnly(!editable); +} + +bool QtVCardDescriptionField::isEmpty() const { + return ui->plainTextEditDESC->toPlainText().isEmpty(); +} + +void QtVCardDescriptionField::setDescription(const QString description) { + ui->plainTextEditDESC->setPlainText(description); +} + +QString QtVCardDescriptionField::getDescription() const { + return ui->plainTextEditDESC->toPlainText(); +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardDescriptionField.h b/Swift/QtUI/QtVCardWidget/QtVCardDescriptionField.h new file mode 100644 index 0000000..22c3a72 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardDescriptionField.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include "QtVCardFieldInfo.h" + +namespace Swift { + + namespace Ui { + class QtVCardDescriptionField; + } + + class QtVCardDescriptionField : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_PROPERTY(bool empty READ isEmpty) + + public : + class FieldInfo : public QtVCardFieldInfo { + public: + virtual ~FieldInfo() { + } + virtual QString getMenuName() const { + return tr("Description"); + } + virtual int getAllowedInstances() const { + return 1; + } + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const { + return new QtVCardDescriptionField(parent, editable); + } + virtual bool testInstance(QWidget* widget) const { + return dynamic_cast<QtVCardDescriptionField*>(widget) != 0; + } + }; + + public: + explicit QtVCardDescriptionField(QWidget* parent = 0, bool editable = false); + ~QtVCardDescriptionField(); + + bool isEditable() const; + void setEditable(bool); + + bool isEmpty() const; + + void setDescription(const QString description); + QString getDescription() const; + + private: + Ui::QtVCardDescriptionField* ui; + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardDescriptionField.ui b/Swift/QtUI/QtVCardWidget/QtVCardDescriptionField.ui new file mode 100644 index 0000000..9ca3fe5 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardDescriptionField.ui @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Swift::QtVCardDescriptionField</class> + <widget class="QWidget" name="Swift::QtVCardDescriptionField"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>488</width> + <height>170</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QPlainTextEdit" name="plainTextEditDESC"> + <property name="toolTip"> + <string>Description</string> + </property> + <property name="documentTitle"> + <string/> + </property> + <property name="lineWrapMode"> + <enum>QPlainTextEdit::NoWrap</enum> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardEMailField.cpp b/Swift/QtUI/QtVCardWidget/QtVCardEMailField.cpp new file mode 100644 index 0000000..58372c2 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardEMailField.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardEMailField.h" +#include "ui_QtVCardEMailField.h" + +#include <QVariant> + +namespace Swift { + +QtVCardEMailField::QtVCardEMailField(QWidget* parent, bool editable) : + QWidget(parent), + ui(new Ui::QtVCardEMailField) { + ui->setupUi(this); + connect(ui->lineEditEMAIL, SIGNAL(textChanged(QString)), SLOT(onTextChanged(QString))); + connect(ui->comboBoxType, SIGNAL(currentIndexChanged(int)), SLOT(onEMailTypeChanged(int))); + setEditable(editable); +} + +QtVCardEMailField::~QtVCardEMailField() { + delete ui; +} + +bool QtVCardEMailField::isEditable() const { + return editable; +} + +void QtVCardEMailField::setEditable(bool editable) { + this->editable = editable; + if (this->editable) { + ui->label->show(); + ui->comboBoxType->show(); + ui->lineEditEMAIL->show(); + ui->labelEMAIL->hide(); + } else { + ui->label->hide(); + ui->comboBoxType->hide(); + ui->lineEditEMAIL->hide(); + ui->labelEMAIL->show(); + } + + foreach(QObject* widget, children()) { + if (!dynamic_cast<QWidget*>(widget)) continue; + if (widget->property("editable").isValid()) { + widget->setProperty("editable", QVariant(editable)); + } + + if (widget->property("readOnly").isValid()) { + widget->setProperty("readOnly", QVariant(!editable)); + widget->setProperty("frame", QVariant(editable)); + } + + QCheckBox* checkbox; + if ((checkbox = dynamic_cast<QCheckBox*>(widget))) { + checkbox->setProperty("enabled", QVariant(editable)); + } + } +} + +bool QtVCardEMailField::isEmpty() const { + return ui->lineEditEMAIL->text().isEmpty(); +} + +void QtVCardEMailField::setAddress(const QString address) { + ui->lineEditEMAIL->setText(address); +} + +QString QtVCardEMailField::getAddress() const { + return ui->lineEditEMAIL->text(); +} + +void QtVCardEMailField::setPreferred(const bool preferred) { + ui->checkBoxPREF->setChecked(preferred); +} + +bool QtVCardEMailField::getPreferred() const { + return ui->checkBoxPREF->checkState() == Qt::Checked; +} + +void QtVCardEMailField::setHome(const bool home) { + ui->checkBoxHOME->setChecked(home); +} + +bool QtVCardEMailField::getHome() const { + return ui->checkBoxHOME->checkState() == Qt::Checked; +} + +void QtVCardEMailField::setWork(const bool work) { + ui->checkBoxWORK->setChecked(work); +} + +bool QtVCardEMailField::getWork() const { + return ui->checkBoxWORK->checkState() == Qt::Checked; +} + +void QtVCardEMailField::setType(EMailType type) { + ui->comboBoxType->setCurrentIndex(type); +} + +QtVCardEMailField::EMailType QtVCardEMailField::getType() const { + return ui->comboBoxType->currentIndex() == 1 ? X_400 : Internet; +} + +void QtVCardEMailField::onTextChanged(const QString& text) { + if (ui->comboBoxType->currentIndex() == Internet && isEmailAddress(text)) { + ui->labelEMAIL->setText(QString("<a href=\"mailto:%1\">%1</a>").arg(text)); + } else { + ui->labelEMAIL->setText(text); + } +} + +void QtVCardEMailField::onEMailTypeChanged(int) { + onTextChanged(ui->labelEMAIL->text()); +} + +bool QtVCardEMailField::isEmailAddress(const QString& emailAddress) { + if ( emailAddress.length() == 0 ) { + return false; + } + QRegExp regex(QString("\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b"), Qt::CaseInsensitive); + return regex.exactMatch(emailAddress); +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardEMailField.h b/Swift/QtUI/QtVCardWidget/QtVCardEMailField.h new file mode 100644 index 0000000..ff486a1 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardEMailField.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include "QtVCardFieldInfo.h" + +namespace Swift { + + namespace Ui { + class QtVCardEMailField; + } + + class QtVCardEMailField : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_PROPERTY(bool empty READ isEmpty) + + public : + class FieldInfo : public QtVCardFieldInfo { + public: + virtual ~FieldInfo() { + } + virtual QString getMenuName() const { + return tr("EMail"); + } + virtual int getAllowedInstances() const { + return UNLIMITED_INSTANCES; + } + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const { + return new QtVCardEMailField(parent, editable); + } + virtual bool testInstance(QWidget* widget) const { + return dynamic_cast<QtVCardEMailField*>(widget) != 0; + } + }; + + enum EMailType { + Internet = 0, + X_400 + }; + + public: + explicit QtVCardEMailField(QWidget* parent = 0, bool editable = false); + ~QtVCardEMailField(); + + bool isEditable() const; + void setEditable(bool); + + bool isEmpty() const; + + void setAddress(const QString address); + QString getAddress() const; + + void setPreferred(const bool preferred); + bool getPreferred() const; + + void setHome(const bool home); + bool getHome() const; + + void setWork(const bool work); + bool getWork() const; + + void setType(EMailType type); + EMailType getType() const; + + private slots: + void onTextChanged(const QString&); + void onEMailTypeChanged(int); + + private: + bool isEmailAddress(const QString& emailAddress); + + private: + Ui::QtVCardEMailField* ui; + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardEMailField.ui b/Swift/QtUI/QtVCardWidget/QtVCardEMailField.ui new file mode 100644 index 0000000..abf0fa1 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardEMailField.ui @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Swift::QtVCardEMailField</class> + <widget class="QWidget" name="Swift::QtVCardEMailField"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>517</width> + <height>29</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Type:</string> + </property> + <property name="buddy"> + <cstring>comboBoxType</cstring> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="comboBoxType"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="editable"> + <bool>false</bool> + </property> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum> + </property> + <property name="minimumContentsLength"> + <number>1</number> + </property> + <item> + <property name="text"> + <string>Internet</string> + </property> + </item> + <item> + <property name="text"> + <string>X.400</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QLabel" name="labelEMAIL"> + <property name="toolTip"> + <string>E-Mail</string> + </property> + <property name="text"> + <string/> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditEMAIL"> + <property name="toolTip"> + <string>E-Mail</string> + </property> + <property name="placeholderText"> + <string>E-Mail</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QCheckBox" name="checkBoxPREF"> + <property name="text"> + <string>Preferred</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBoxHOME"> + <property name="text"> + <string>Home</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBoxWORK"> + <property name="text"> + <string>Work</string> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Swift::QtResizableLineEdit</class> + <extends>QLineEdit</extends> + <header>QtResizableLineEdit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardFieldInfo.h b/Swift/QtUI/QtVCardWidget/QtVCardFieldInfo.h new file mode 100644 index 0000000..8a9d089 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardFieldInfo.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <typeinfo> + +class QWidget; + +namespace Swift { + + class QtVCardFieldInfo { + public: + static const int UNLIMITED_INSTANCES = -1; + + virtual ~QtVCardFieldInfo() { + } + virtual QString getMenuName() const = 0; + virtual int getAllowedInstances() const = 0; + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const = 0; + virtual bool testInstance(QWidget*) const = 0; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardJIDField.cpp b/Swift/QtUI/QtVCardWidget/QtVCardJIDField.cpp new file mode 100644 index 0000000..69e2285 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardJIDField.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardJIDField.h" +#include "ui_QtVCardJIDField.h" + +#include <Swiften/JID/JID.h> + +#include <Swift/QtUI/QtSwiftUtil.h> + +namespace Swift { + +QtVCardJIDField::QtVCardJIDField(QWidget* parent, bool editable) : + QWidget(parent), + ui(new Ui::QtVCardJIDField) { + ui->setupUi(this); + connect(ui->lineEditJID, SIGNAL(textChanged(QString)), SLOT(onTextChanged(QString))); + setEditable(editable); +} + +QtVCardJIDField::~QtVCardJIDField() { + delete ui; +} + +bool QtVCardJIDField::isEditable() const { + return editable; +} + +void QtVCardJIDField::setEditable(bool editable) { + this->editable = editable; + if (this->editable) { + ui->lineEditJID->show(); + ui->labelJID->hide(); + } else { + ui->lineEditJID->hide(); + ui->labelJID->show(); + } +} + +bool QtVCardJIDField::isEmpty() const { + return ui->lineEditJID->text().isEmpty(); +} + +void QtVCardJIDField::setJID(const QString jid) { + ui->lineEditJID->setText(jid); +} + +QString QtVCardJIDField::getJID() const { + return ui->lineEditJID->text(); +} + +void QtVCardJIDField::onTextChanged(const QString& text) { + if (text.isEmpty()) { + ui->labelJID->setText(""); + } else { + if (JID(Q2PSTRING(text)).isValid()) { + ui->labelJID->setText(QString("<a href=\"xmpp:%1\">%1</a>").arg(text)); + } else { + ui->labelJID->setText(text); + } + } +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardJIDField.h b/Swift/QtUI/QtVCardWidget/QtVCardJIDField.h new file mode 100644 index 0000000..bd697de --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardJIDField.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include "QtVCardFieldInfo.h" + +namespace Swift { + + namespace Ui { + class QtVCardJIDField; + } + + class QtVCardJIDField : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_PROPERTY(bool empty READ isEmpty) + + public : + class FieldInfo : public QtVCardFieldInfo { + public: + virtual ~FieldInfo() { + } + virtual QString getMenuName() const { + return tr("JID"); + } + virtual int getAllowedInstances() const { + return UNLIMITED_INSTANCES; + } + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const { + return new QtVCardJIDField(parent, editable); + } + virtual bool testInstance(QWidget* widget) const { + return dynamic_cast<QtVCardJIDField*>(widget) != 0; + } + }; + + public: + explicit QtVCardJIDField(QWidget* parent = 0, bool editable = false); + ~QtVCardJIDField(); + + bool isEditable() const; + void setEditable(bool); + + bool isEmpty() const; + + void setJID(const QString jid); + QString getJID() const; + + private slots: + void onTextChanged(const QString&); + + private: + Ui::QtVCardJIDField* ui; + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardJIDField.ui b/Swift/QtUI/QtVCardWidget/QtVCardJIDField.ui new file mode 100644 index 0000000..7215578 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardJIDField.ui @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Swift::QtVCardJIDField</class> + <widget class="QWidget" name="Swift::QtVCardJIDField"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>517</width> + <height>29</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="labelJID"> + <property name="toolTip"> + <string>JID</string> + </property> + <property name="text"> + <string/> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditJID"> + <property name="toolTip"> + <string>JID</string> + </property> + <property name="placeholderText"> + <string>JID</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Swift::QtResizableLineEdit</class> + <extends>QLineEdit</extends> + <header>QtResizableLineEdit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardOrganisationField.cpp b/Swift/QtUI/QtVCardWidget/QtVCardOrganisationField.cpp new file mode 100644 index 0000000..37d35d9 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardOrganisationField.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardOrganisationField.h" +#include "ui_QtVCardOrganisationField.h" + +namespace Swift { + +QtVCardOrganisationField::QtVCardOrganisationField(QWidget* parent, bool editable) : + QWidget(parent), + ui(new Ui::QtVCardOrganisationField) { + ui->setupUi(this); + connect(ui->lineEditORGNAME, SIGNAL(textChanged(QString)), SLOT(onTextChanged(QString))); + connect(ui->pushButtonAddUnit, SIGNAL(clicked()), SLOT(onAddUnitButtonPressed())); + connect(ui->pushButtonRemoveUnit, SIGNAL(clicked()), SLOT(onRemoveUnitButtonPressed())); + setEditable(editable); +} + +QtVCardOrganisationField::~QtVCardOrganisationField() { + delete ui; +} + +bool QtVCardOrganisationField::isEditable() const { + return editable; +} + +void QtVCardOrganisationField::setEditable(bool editable) { + this->editable = editable; + if (this->editable) { + ui->lineEditORGNAME->show(); + ui->labelORGNAME->hide(); + ui->listWidgetORGUNIT->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed); + ui->listWidgetORGUNIT->setEnabled(true); + ui->pushButtonAddUnit->show(); + ui->pushButtonRemoveUnit->show(); + } else { + ui->lineEditORGNAME->hide(); + ui->labelORGNAME->show(); + if (ui->listWidgetORGUNIT->count() > 0) { + ui->listWidgetORGUNIT->setEditTriggers(0); + ui->listWidgetORGUNIT->show(); + } else { + ui->listWidgetORGUNIT->hide(); + } + ui->pushButtonAddUnit->hide(); + ui->pushButtonRemoveUnit->hide(); + } +} + +bool QtVCardOrganisationField::isEmpty() const { + return ui->lineEditORGNAME->text().isEmpty() && getUnits().empty(); +} + +void QtVCardOrganisationField::setName(const QString name) { + ui->lineEditORGNAME->setText(name); +} + +QString QtVCardOrganisationField::getName() const { + return ui->lineEditORGNAME->text(); +} + +void QtVCardOrganisationField::setUnits(const QList<QString> units) { + ui->listWidgetORGUNIT->clear(); + foreach(const QString& unit, units) { + QListWidgetItem* item = new QListWidgetItem(unit); + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->listWidgetORGUNIT->addItem(item); + } +} + +QList<QString> QtVCardOrganisationField::getUnits() const { + QList<QString> units; + for (int n = 0; n < ui->listWidgetORGUNIT->count(); n++) { + QListWidgetItem* item = ui->listWidgetORGUNIT->item(n); + units.push_back(item->text()); + } + return units; +} + +void QtVCardOrganisationField::onTextChanged(const QString& text) { + ui->labelORGNAME->setText(text); +} + +void QtVCardOrganisationField::onAddUnitButtonPressed() { + QListWidgetItem* item = new QListWidgetItem("Doubleclick to edit."); + item->setFlags(item->flags() | Qt::ItemIsEditable); + ui->listWidgetORGUNIT->addItem(item); +} + +void QtVCardOrganisationField::onRemoveUnitButtonPressed() { + foreach (QListWidgetItem* item, ui->listWidgetORGUNIT->selectedItems()) { + ui->listWidgetORGUNIT->removeItemWidget(item); + delete item; + } +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardOrganisationField.h b/Swift/QtUI/QtVCardWidget/QtVCardOrganisationField.h new file mode 100644 index 0000000..0743823 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardOrganisationField.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include "QtVCardFieldInfo.h" + +namespace Swift { + + namespace Ui { + class QtVCardOrganisationField; + } + + class QtVCardOrganisationField : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_PROPERTY(bool empty READ isEmpty) + + public : + class FieldInfo : public QtVCardFieldInfo { + public: + virtual ~FieldInfo() { + } + virtual QString getMenuName() const { + return tr("Organisation"); + } + virtual int getAllowedInstances() const { + return UNLIMITED_INSTANCES; + } + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const { + return new QtVCardOrganisationField(parent, editable); + } + virtual bool testInstance(QWidget* widget) const { + return dynamic_cast<QtVCardOrganisationField*>(widget) != 0; + } + }; + + public: + explicit QtVCardOrganisationField(QWidget* parent = 0, bool editable = false); + ~QtVCardOrganisationField(); + + bool isEditable() const; + void setEditable(bool); + + bool isEmpty() const; + + void setName(const QString name); + QString getName() const; + + void setUnits(const QList<QString> units); + QList<QString> getUnits() const; + + private slots: + void onTextChanged(const QString&); + void onAddUnitButtonPressed(); + void onRemoveUnitButtonPressed(); + + private: + Ui::QtVCardOrganisationField* ui; + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardOrganisationField.ui b/Swift/QtUI/QtVCardWidget/QtVCardOrganisationField.ui new file mode 100644 index 0000000..1caf2b1 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardOrganisationField.ui @@ -0,0 +1,169 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Swift::QtVCardOrganisationField</class> + <widget class="QWidget" name="Swift::QtVCardOrganisationField"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>455</width> + <height>112</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="labelORGNAME"> + <property name="toolTip"> + <string>Organisation Name</string> + </property> + <property name="text"> + <string/> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditORGNAME"> + <property name="toolTip"> + <string>Organisation Name</string> + </property> + <property name="placeholderText"> + <string>Organisation Name</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item row="1" column="0" colspan="2"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="spacing"> + <number>5</number> + </property> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButtonRemoveUnit"> + <property name="text"> + <string>Remove Unit</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButtonAddUnit"> + <property name="text"> + <string>Add Unit</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="0"> + <widget class="QListWidget" name="listWidgetORGUNIT"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Organisation Units</string> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::MultiSelection</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Swift::QtResizableLineEdit</class> + <extends>QLineEdit</extends> + <header>QtResizableLineEdit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardPhotoAndNameFields.cpp b/Swift/QtUI/QtVCardWidget/QtVCardPhotoAndNameFields.cpp new file mode 100644 index 0000000..2c6ef22 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardPhotoAndNameFields.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardPhotoAndNameFields.h" +#include "ui_QtVCardPhotoAndNameFields.h" + +#include <QDebug> +#include <QMenu> + +namespace Swift { + +QtVCardPhotoAndNameFields::QtVCardPhotoAndNameFields(QWidget* parent) : + QWidget(parent), + ui(new Ui::QtVCardPhotoAndNameFields) { + ui->setupUi(this); + ui->lineEditPREFIX->hide(); + ui->lineEditMIDDLE->hide(); + ui->lineEditSUFFIX->hide(); + ui->lineEditFN->hide(); + ui->lineEditNICKNAME->hide(); + + addFieldMenu = new QMenu("Name", this); + + actionSignalMapper = new QSignalMapper(this); + + connect(actionSignalMapper, SIGNAL(mapped(const QString &)), this, SLOT(showField(const QString &))); + prepareAddFieldMenu(); +} + +QtVCardPhotoAndNameFields::~QtVCardPhotoAndNameFields() { + delete ui; + delete actionSignalMapper; +} + +bool QtVCardPhotoAndNameFields::isEditable() const { + return editable; +} + +void QtVCardPhotoAndNameFields::setEditable(bool editable) { + this->editable = editable; + + foreach(QObject *widget, children()) { + if (!dynamic_cast<QWidget*>(widget)) continue; + if (widget->property("editable").isValid()) { + widget->setProperty("editable", QVariant(editable)); + } + + if (widget->property("readOnly").isValid()) { + widget->setProperty("readOnly", QVariant(!editable)); + widget->setProperty("frame", QVariant(editable)); + } + QLineEdit* lineEdit = 0; + if ((lineEdit = dynamic_cast<QLineEdit*>(widget))) { + if (lineEdit->text().isEmpty()) { + lineEdit->hide(); + } else { + lineEdit->show(); + } + } + } + prepareAddFieldMenu(); +} + +QMenu* QtVCardPhotoAndNameFields::getAddFieldMenu() const { + return addFieldMenu; +} + +void QtVCardPhotoAndNameFields::setAvatar(const ByteArray &data, const std::string &type) { + ui->avatarWidget->setAvatar(data, type); +} + +ByteArray QtVCardPhotoAndNameFields::getAvatarData() const { + return ui->avatarWidget->getAvatarData(); +} + +std::string QtVCardPhotoAndNameFields::getAvatarType() const { + return ui->avatarWidget->getAvatarType(); +} + +void QtVCardPhotoAndNameFields::setFormattedName(const QString formattedName) { + ui->lineEditFN->setText(formattedName); +} + +QString QtVCardPhotoAndNameFields::getFormattedName() const { + return ui->lineEditFN->text(); +} + +void QtVCardPhotoAndNameFields::setNickname(const QString nickname) { + ui->lineEditNICKNAME->setText(nickname); +} + +QString QtVCardPhotoAndNameFields::getNickname() const { + return ui->lineEditNICKNAME->text(); +} + +void QtVCardPhotoAndNameFields::setPrefix(const QString prefix) { + ui->lineEditPREFIX->setText(prefix); +} + +QString QtVCardPhotoAndNameFields::getPrefix() const { + return ui->lineEditPREFIX->text(); +} + +void QtVCardPhotoAndNameFields::setGivenName(const QString givenName) { + ui->lineEditGIVEN->setText(givenName); +} + +QString QtVCardPhotoAndNameFields::getGivenName() const { + return ui->lineEditGIVEN->text(); +} + +void QtVCardPhotoAndNameFields::setMiddleName(const QString middleName) { + ui->lineEditMIDDLE->setText(middleName); +} + +QString QtVCardPhotoAndNameFields::getMiddleName() const { + return ui->lineEditMIDDLE->text(); +} + +void QtVCardPhotoAndNameFields::setFamilyName(const QString familyName) { + ui->lineEditFAMILY->setText(familyName); +} + +QString QtVCardPhotoAndNameFields::getFamilyName() const { + return ui->lineEditFAMILY->text(); +} + +void QtVCardPhotoAndNameFields::setSuffix(const QString suffix) { + ui->lineEditSUFFIX->setText(suffix); +} + +QString QtVCardPhotoAndNameFields::getSuffix() const { + return ui->lineEditSUFFIX->text(); +} + +void QtVCardPhotoAndNameFields::prepareAddFieldMenu() { + foreach(QAction* action, addFieldMenu->actions()) { + actionSignalMapper->removeMappings(action); + } + + addFieldMenu->clear(); + foreach(QObject* obj, children()) { + QLineEdit* lineEdit = 0; + if (!(lineEdit = dynamic_cast<QLineEdit*>(obj))) continue; + if (lineEdit->isHidden()) { + QAction* action = addFieldMenu->addAction(QString("Add ") + lineEdit->placeholderText(), actionSignalMapper, SLOT(map())); + actionSignalMapper->setMapping(action, lineEdit->objectName()); + } + } +} + +void QtVCardPhotoAndNameFields::showField(const QString& widgetName) { + QLineEdit* lineEditToShow = findChild<QLineEdit*>(widgetName); + if (lineEditToShow) lineEditToShow->show(); + + prepareAddFieldMenu(); +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardPhotoAndNameFields.h b/Swift/QtUI/QtVCardWidget/QtVCardPhotoAndNameFields.h new file mode 100644 index 0000000..2fb7e0a --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardPhotoAndNameFields.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QMenu> +#include <QSignalMapper> +#include <QWidget> + +#include <Swiften/Base/ByteArray.h> + +namespace Ui { + class QtVCardPhotoAndNameFields; +} + + +namespace Swift { + + class QtVCardPhotoAndNameFields : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + + public : + explicit QtVCardPhotoAndNameFields(QWidget* parent = 0); + ~QtVCardPhotoAndNameFields(); + + bool isEditable() const; + void setEditable(bool); + + QMenu* getAddFieldMenu() const; + + void setAvatar(const ByteArray& data, const std::string& type); + ByteArray getAvatarData() const; + std::string getAvatarType() const; + + void setFormattedName(const QString formattedName); + QString getFormattedName() const; + + void setNickname(const QString nickname); + QString getNickname() const; + + void setPrefix(const QString prefix); + QString getPrefix() const; + + void setGivenName(const QString givenName); + QString getGivenName() const; + + void setMiddleName(const QString middleName); + QString getMiddleName() const; + + void setFamilyName(const QString familyName); + QString getFamilyName() const; + + void setSuffix(const QString suffix); + QString getSuffix() const; + + public slots: + void showField(const QString& widgetName); + + private: + void prepareAddFieldMenu(); + + private: + Ui::QtVCardPhotoAndNameFields* ui; + bool editable; + + QMenu* addFieldMenu; + QSignalMapper* actionSignalMapper; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardPhotoAndNameFields.ui b/Swift/QtUI/QtVCardWidget/QtVCardPhotoAndNameFields.ui new file mode 100644 index 0000000..a30878e --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardPhotoAndNameFields.ui @@ -0,0 +1,260 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtVCardPhotoAndNameFields</class> + <widget class="QWidget" name="QtVCardPhotoAndNameFields"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>522</width> + <height>81</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0" rowminimumheight="0,0,0,0,0"> + <property name="sizeConstraint"> + <enum>QLayout::SetMinimumSize</enum> + </property> + <property name="horizontalSpacing"> + <number>5</number> + </property> + <property name="verticalSpacing"> + <number>1</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item row="0" column="0" rowspan="5"> + <widget class="Swift::QtAvatarWidget" name="avatarWidget" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" stdset="0"> + <string/> + </property> + <property name="flat" stdset="0"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditFN"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="font"> + <font> + <pointsize>18</pointsize> + </font> + </property> + <property name="toolTip"> + <string>Formatted Name</string> + </property> + <property name="placeholderText"> + <string>Formatted Name</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="1" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditNICKNAME"> + <property name="toolTip"> + <string>Nickname</string> + </property> + <property name="frame"> + <bool>true</bool> + </property> + <property name="placeholderText"> + <string>Nickname</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="2" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>2</number> + </property> + <property name="sizeConstraint"> + <enum>QLayout::SetMinimumSize</enum> + </property> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditPREFIX"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Prefix</string> + </property> + <property name="placeholderText"> + <string>Prefix</string> + </property> + </widget> + </item> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditGIVEN"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Given Name</string> + </property> + <property name="text"> + <string/> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="placeholderText"> + <string>Given Name</string> + </property> + </widget> + </item> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditMIDDLE"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Middle Name</string> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="frame"> + <bool>true</bool> + </property> + <property name="placeholderText"> + <string>Middle Name</string> + </property> + </widget> + </item> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditFAMILY"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Last Name</string> + </property> + <property name="placeholderText"> + <string>Last Name</string> + </property> + </widget> + </item> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditSUFFIX"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Suffix</string> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="placeholderText"> + <string>Suffix</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Swift::QtResizableLineEdit</class> + <extends>QLineEdit</extends> + <header>QtResizableLineEdit.h</header> + </customwidget> + <customwidget> + <class>Swift::QtAvatarWidget</class> + <extends>QWidget</extends> + <header>Swift/QtUI/QtAvatarWidget.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardRoleField.cpp b/Swift/QtUI/QtVCardWidget/QtVCardRoleField.cpp new file mode 100644 index 0000000..d35f732 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardRoleField.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardRoleField.h" +#include "ui_QtVCardRoleField.h" + +namespace Swift { + +QtVCardRoleField::QtVCardRoleField(QWidget* parent, bool editable) : + QWidget(parent), + ui(new Ui::QtVCardRoleField) { + ui->setupUi(this); + connect(ui->lineEditROLE, SIGNAL(textChanged(QString)), SLOT(onTextChanged(QString))); + setEditable(editable); +} + +QtVCardRoleField::~QtVCardRoleField() { + delete ui; +} + +bool QtVCardRoleField::isEditable() const { + return editable; +} + +void QtVCardRoleField::setEditable(bool editable) { + this->editable = editable; + if (this->editable) { + ui->lineEditROLE->show(); + ui->labelROLE->hide(); + } else { + ui->lineEditROLE->hide(); + ui->labelROLE->show(); + } +} + +bool QtVCardRoleField::isEmpty() const { + return ui->lineEditROLE->text().isEmpty(); +} + +void QtVCardRoleField::setRole(const QString role) { + ui->lineEditROLE->setText(role); +} + +QString QtVCardRoleField::getRole() const { + return ui->lineEditROLE->text(); +} + +void QtVCardRoleField::onTextChanged(const QString& text) { + ui->labelROLE->setText(text); +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardRoleField.h b/Swift/QtUI/QtVCardWidget/QtVCardRoleField.h new file mode 100644 index 0000000..f728170 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardRoleField.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include "QtVCardFieldInfo.h" + +namespace Swift { + + namespace Ui { + class QtVCardRoleField; + } + + class QtVCardRoleField : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_PROPERTY(bool empty READ isEmpty) + + public : + class FieldInfo : public QtVCardFieldInfo { + public: + virtual ~FieldInfo() { + } + virtual QString getMenuName() const { + return tr("Role"); + } + virtual int getAllowedInstances() const { + return UNLIMITED_INSTANCES; + } + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const { + return new QtVCardRoleField(parent, editable); + } + virtual bool testInstance(QWidget* widget) const { + return dynamic_cast<QtVCardRoleField*>(widget) != 0; + } + }; + + public: + explicit QtVCardRoleField(QWidget* parent = 0, bool editable = false); + ~QtVCardRoleField(); + + bool isEditable() const; + void setEditable(bool); + + bool isEmpty() const; + + void setRole(const QString role); + QString getRole() const; + + private slots: + void onTextChanged(const QString&); + + private: + Ui::QtVCardRoleField* ui; + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardRoleField.ui b/Swift/QtUI/QtVCardWidget/QtVCardRoleField.ui new file mode 100644 index 0000000..f6c482b --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardRoleField.ui @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Swift::QtVCardRoleField</class> + <widget class="QWidget" name="Swift::QtVCardRoleField"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>517</width> + <height>29</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="labelROLE"> + <property name="toolTip"> + <string>Role</string> + </property> + <property name="text"> + <string/> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditROLE"> + <property name="toolTip"> + <string>Role</string> + </property> + <property name="placeholderText"> + <string>Role</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Swift::QtResizableLineEdit</class> + <extends>QLineEdit</extends> + <header>QtResizableLineEdit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardTelephoneField.cpp b/Swift/QtUI/QtVCardWidget/QtVCardTelephoneField.cpp new file mode 100644 index 0000000..cbc16bd --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardTelephoneField.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardTelephoneField.h" +#include "ui_QtVCardTelephoneField.h" + +#define GETTER_SETTER_IMPL( METHOD_NAME, UI_NAME ) \ + void QtVCardTelephoneField::set##METHOD_NAME(const bool METHOD_NAME) { \ + ui->checkBox##UI_NAME->setChecked(METHOD_NAME); \ + } \ + \ + bool QtVCardTelephoneField::get##METHOD_NAME() const { \ + return ui->checkBox##UI_NAME->checkState() == Qt::Checked; \ + } + +namespace Swift { + +QtVCardTelephoneField::QtVCardTelephoneField(QWidget* parent, bool editable) : + QWidget(parent), + ui(new Ui::QtVCardTelephoneField) { + ui->setupUi(this); + connect(ui->lineEditTEL, SIGNAL(textChanged(QString)), SLOT(onTextChanged(QString))); + setEditable(editable); +} + +QtVCardTelephoneField::~QtVCardTelephoneField() { + delete ui; +} + +bool QtVCardTelephoneField::isEditable() const { + return editable; +} + +void QtVCardTelephoneField::setEditable(bool editable) { + this->editable = editable; + if (this->editable) { + ui->lineEditTEL->show(); + ui->labelTEL->hide(); + } else { + ui->lineEditTEL->hide(); + ui->labelTEL->show(); + } + + foreach(QObject *widget, children()) { + if (!dynamic_cast<QWidget*>(widget)) continue; + if (widget->property("editable").isValid()) { + widget->setProperty("editable", QVariant(editable)); + } + + if (widget->property("readOnly").isValid()) { + widget->setProperty("readOnly", QVariant(!editable)); + widget->setProperty("frame", QVariant(editable)); + } + + QCheckBox* checkbox; + if ((checkbox = dynamic_cast<QCheckBox*>(widget))) { + checkbox->setProperty("enabled", QVariant(editable)); + } + } +} + +bool QtVCardTelephoneField::isEmpty() const { + return ui->lineEditTEL->text().isEmpty(); +} + +void QtVCardTelephoneField::setNumber(const QString number) { + ui->lineEditTEL->setText(number); +} + +QString QtVCardTelephoneField::getNumber() const { + return ui->lineEditTEL->text(); +} + +GETTER_SETTER_IMPL(Preferred, PREF) +GETTER_SETTER_IMPL(Home, HOME) +GETTER_SETTER_IMPL(Work, WORK) +GETTER_SETTER_IMPL(Voice, VOICE) +GETTER_SETTER_IMPL(Fax, FAX) +GETTER_SETTER_IMPL(Pager, PAGER) +GETTER_SETTER_IMPL(MSG, MSG) +GETTER_SETTER_IMPL(Cell, CELL) +GETTER_SETTER_IMPL(Video, VIDEO) +GETTER_SETTER_IMPL(BBS, BBS) +GETTER_SETTER_IMPL(Modem, MODEM) +GETTER_SETTER_IMPL(ISDN, ISDN) +GETTER_SETTER_IMPL(PCS, PCS) + +void QtVCardTelephoneField::onTextChanged(const QString& text) { + ui->labelTEL->setText(text); +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardTelephoneField.h b/Swift/QtUI/QtVCardWidget/QtVCardTelephoneField.h new file mode 100644 index 0000000..d3c6bb2 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardTelephoneField.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include "QtVCardFieldInfo.h" + +namespace Swift { + + namespace Ui { + class QtVCardTelephoneField; + } + + class QtVCardTelephoneField : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_PROPERTY(bool empty READ isEmpty) + + public : + class FieldInfo : public QtVCardFieldInfo { + public: + virtual ~FieldInfo() { + } + virtual QString getMenuName() const { + return tr("Telephone"); + } + virtual int getAllowedInstances() const { + return UNLIMITED_INSTANCES; + } + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const { + return new QtVCardTelephoneField(parent, editable); + } + virtual bool testInstance(QWidget* widget) const { + return dynamic_cast<QtVCardTelephoneField*>(widget) != 0; + } + }; + + public: + explicit QtVCardTelephoneField(QWidget* parent = 0, bool editable = false); + ~QtVCardTelephoneField(); + + bool isEditable() const; + void setEditable(bool); + + bool isEmpty() const; + + void setNumber(const QString address); + QString getNumber() const; + + void setPreferred(const bool preferred); + bool getPreferred() const; + + void setHome(const bool home); + bool getHome() const; + + void setWork(const bool work); + bool getWork() const; + + void setVoice(const bool); + bool getVoice() const; + void setFax(const bool); + bool getFax() const; + void setPager(const bool); + bool getPager() const; + void setMSG(const bool); + bool getMSG() const; + void setCell(const bool); + bool getCell() const; + void setVideo(const bool); + bool getVideo() const; + void setBBS(const bool); + bool getBBS() const; + void setModem(const bool); + bool getModem() const; + void setISDN(const bool); + bool getISDN() const; + void setPCS(const bool); + bool getPCS() const; + + private slots: + void onTextChanged(const QString&); + + private: + Ui::QtVCardTelephoneField* ui; + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardTelephoneField.ui b/Swift/QtUI/QtVCardWidget/QtVCardTelephoneField.ui new file mode 100644 index 0000000..3b100bb --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardTelephoneField.ui @@ -0,0 +1,174 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Swift::QtVCardTelephoneField</class> + <widget class="QWidget" name="Swift::QtVCardTelephoneField"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>629</width> + <height>174</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="labelTEL"> + <property name="toolTip"> + <string>Telephone</string> + </property> + <property name="text"> + <string/> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditTEL"> + <property name="toolTip"> + <string>Telephone</string> + </property> + <property name="placeholderText"> + <string>Telephone</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBoxPREF"> + <property name="text"> + <string>Preferred</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QCheckBox" name="checkBoxHOME"> + <property name="text"> + <string>Home</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QCheckBox" name="checkBoxWORK"> + <property name="text"> + <string>Work</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBoxVOICE"> + <property name="text"> + <string>Voice</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QCheckBox" name="checkBoxCELL"> + <property name="text"> + <string>Cell</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="checkBoxPAGER"> + <property name="text"> + <string>Pager</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="checkBoxISDN"> + <property name="text"> + <string>ISDN</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QCheckBox" name="checkBoxVIDEO"> + <property name="text"> + <string>Video</string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QCheckBox" name="checkBoxMSG"> + <property name="text"> + <string>Voice Messaging Service</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QCheckBox" name="checkBoxFAX"> + <property name="text"> + <string>Fax</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QCheckBox" name="checkBoxMODEM"> + <property name="text"> + <string>Modem</string> + </property> + </widget> + </item> + <item row="2" column="2" colspan="2"> + <widget class="QCheckBox" name="checkBoxPCS"> + <property name="text"> + <string>Personal Communication Service</string> + </property> + </widget> + </item> + <item row="3" column="2" colspan="2"> + <widget class="QCheckBox" name="checkBoxBBS"> + <property name="text"> + <string>Bulletin Board System</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Swift::QtResizableLineEdit</class> + <extends>QLineEdit</extends> + <header>QtResizableLineEdit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardTitleField.cpp b/Swift/QtUI/QtVCardWidget/QtVCardTitleField.cpp new file mode 100644 index 0000000..52b8103 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardTitleField.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardTitleField.h" +#include "ui_QtVCardTitleField.h" + +namespace Swift { + +QtVCardTitleField::QtVCardTitleField(QWidget* parent, bool editable) : + QWidget(parent), + ui(new Ui::QtVCardTitleField) { + ui->setupUi(this); + connect(ui->lineEditTITLE, SIGNAL(textChanged(QString)), SLOT(onTextChanged(QString))); + setEditable(editable); +} + +QtVCardTitleField::~QtVCardTitleField() { + delete ui; +} + +bool QtVCardTitleField::isEditable() const { + return editable; +} + +void QtVCardTitleField::setEditable(bool editable) { + this->editable = editable; + if (this->editable) { + ui->lineEditTITLE->show(); + ui->labelTITLE->hide(); + } else { + ui->lineEditTITLE->hide(); + ui->labelTITLE->show(); + } +} + +bool QtVCardTitleField::isEmpty() const { + return ui->lineEditTITLE->text().isEmpty(); +} + +void QtVCardTitleField::setTitle(const QString title) { + ui->lineEditTITLE->setText(title); +} + +QString QtVCardTitleField::getTitle() const { + return ui->lineEditTITLE->text(); +} + +void QtVCardTitleField::onTextChanged(const QString& text) { + ui->labelTITLE->setText(text); +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardTitleField.h b/Swift/QtUI/QtVCardWidget/QtVCardTitleField.h new file mode 100644 index 0000000..1de56e7 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardTitleField.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include "QtVCardFieldInfo.h" + +namespace Swift { + + namespace Ui { + class QtVCardTitleField; + } + + class QtVCardTitleField : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_PROPERTY(bool empty READ isEmpty) + + public : + class FieldInfo : public QtVCardFieldInfo { + public: + virtual ~FieldInfo() { + } + virtual QString getMenuName() const { + return tr("Title"); + } + virtual int getAllowedInstances() const { + return UNLIMITED_INSTANCES; + } + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const { + return new QtVCardTitleField(parent, editable); + } + virtual bool testInstance(QWidget* widget) const { + return dynamic_cast<QtVCardTitleField*>(widget) != 0; + } + }; + + public: + explicit QtVCardTitleField(QWidget* parent = 0, bool editable = false); + ~QtVCardTitleField(); + + bool isEditable() const; + void setEditable(bool); + + bool isEmpty() const; + + void setTitle(const QString title); + QString getTitle() const; + + private slots: + void onTextChanged(const QString&); + + private: + Ui::QtVCardTitleField* ui; + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardTitleField.ui b/Swift/QtUI/QtVCardWidget/QtVCardTitleField.ui new file mode 100644 index 0000000..e5c9013 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardTitleField.ui @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Swift::QtVCardTitleField</class> + <widget class="QWidget" name="Swift::QtVCardTitleField"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>517</width> + <height>29</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="labelTITLE"> + <property name="toolTip"> + <string>Title</string> + </property> + <property name="text"> + <string/> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditTITLE"> + <property name="toolTip"> + <string>Title</string> + </property> + <property name="placeholderText"> + <string>Title</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Swift::QtResizableLineEdit</class> + <extends>QLineEdit</extends> + <header>QtResizableLineEdit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardURLField.cpp b/Swift/QtUI/QtVCardWidget/QtVCardURLField.cpp new file mode 100644 index 0000000..028d729 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardURLField.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardURLField.h" +#include "ui_QtVCardURLField.h" + +#include <QUrl> + +namespace Swift { + +QtVCardURLField::QtVCardURLField(QWidget* parent, bool editable) : + QWidget(parent), + ui(new Ui::QtVCardURLField) { + ui->setupUi(this); + connect(ui->lineEditURL, SIGNAL(textChanged(QString)), SLOT(onTextChanged(QString))); + setEditable(editable); +} + +QtVCardURLField::~QtVCardURLField() { + delete ui; +} + +bool QtVCardURLField::isEditable() const { + return editable; +} + +void QtVCardURLField::setEditable(bool editable) { + this->editable = editable; + if (this->editable) { + ui->lineEditURL->show(); + ui->labelURL->hide(); + } else { + ui->lineEditURL->hide(); + ui->labelURL->show(); + } +} + +bool QtVCardURLField::isEmpty() const { + return ui->lineEditURL->text().isEmpty(); +} + +void QtVCardURLField::setURL(const QString url) { + ui->lineEditURL->setText(url); +} + +QString QtVCardURLField::getURL() const { + return ui->lineEditURL->text(); +} + +void QtVCardURLField::onTextChanged(const QString& text) { + if (text.isEmpty()) { + ui->labelURL->setText(""); + } else { + if (QUrl(text).isValid()) { + ui->labelURL->setText(QString("<a href=\"%1\">%1</a>").arg(text)); + } else { + ui->labelURL->setText(text); + } + } +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardURLField.h b/Swift/QtUI/QtVCardWidget/QtVCardURLField.h new file mode 100644 index 0000000..cb73345 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardURLField.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include "QtVCardFieldInfo.h" + +namespace Swift { + + namespace Ui { + class QtVCardURLField; + } + + class QtVCardURLField : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + Q_PROPERTY(bool empty READ isEmpty) + + public : + class FieldInfo : public QtVCardFieldInfo { + public: + virtual ~FieldInfo() { + } + virtual QString getMenuName() const { + return tr("URL"); + } + virtual int getAllowedInstances() const { + return UNLIMITED_INSTANCES; + } + virtual QWidget* createFieldInstance(QWidget* parent, bool editable) const { + return new QtVCardURLField(parent, editable); + } + virtual bool testInstance(QWidget* widget) const { + return dynamic_cast<QtVCardURLField*>(widget) != 0; + } + }; + + public: + explicit QtVCardURLField(QWidget* parent = 0, bool editable = false); + ~QtVCardURLField(); + + bool isEditable() const; + void setEditable(bool); + + bool isEmpty() const; + + void setURL(const QString url); + QString getURL() const; + + private slots: + void onTextChanged(const QString&); + + private: + Ui::QtVCardURLField* ui; + bool editable; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardURLField.ui b/Swift/QtUI/QtVCardWidget/QtVCardURLField.ui new file mode 100644 index 0000000..984d0b0 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardURLField.ui @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Swift::QtVCardURLField</class> + <widget class="QWidget" name="Swift::QtVCardURLField"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>517</width> + <height>29</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="labelURL"> + <property name="toolTip"> + <string>URL</string> + </property> + <property name="text"> + <string/> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item> + <widget class="Swift::QtResizableLineEdit" name="lineEditURL"> + <property name="toolTip"> + <string>URL</string> + </property> + <property name="placeholderText"> + <string>URL</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Swift::QtResizableLineEdit</class> + <extends>QLineEdit</extends> + <header>QtResizableLineEdit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtVCardWidget/QtVCardWidget.cpp b/Swift/QtUI/QtVCardWidget/QtVCardWidget.cpp new file mode 100644 index 0000000..ac4fca5 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardWidget.cpp @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtVCardWidget.h" +#include "ui_QtVCardWidget.h" + +#include <QDebug> +#include <QLineEdit> +#include <QMenu> + +#include "QtVCardAddressField.h" +#include "QtVCardAddressLabelField.h" +#include "QtVCardBirthdayField.h" +#include "QtVCardDescriptionField.h" +#include "QtVCardEMailField.h" +#include "QtVCardJIDField.h" +#include "QtVCardOrganisationField.h" +#include "QtVCardRoleField.h" +#include "QtVCardTelephoneField.h" +#include "QtVCardTitleField.h" +#include "QtVCardURLField.h" + +#include "QtSwiftUtil.h" + +#include <boost/algorithm/string.hpp> + +#include <Swiften/Base/Log.h> + +namespace Swift { + +QtVCardWidget::QtVCardWidget(QWidget* parent) : + QWidget(parent), + ui(new ::Ui::QtVCardWidget) { + ui->setupUi(this); + + menu = new QMenu(this); + + menu->addMenu(ui->photoAndName->getAddFieldMenu()); + ui->toolButton->setMenu(menu); + + addFieldType(menu, boost::make_shared<QtVCardAddressField::FieldInfo>()); + addFieldType(menu, boost::make_shared<QtVCardEMailField::FieldInfo>()); + addFieldType(menu, boost::make_shared<QtVCardJIDField::FieldInfo>()); + addFieldType(menu, boost::make_shared<QtVCardBirthdayField::FieldInfo>()); + addFieldType(menu, boost::make_shared<QtVCardTelephoneField::FieldInfo>()); + addFieldType(menu, boost::make_shared<QtVCardRoleField::FieldInfo>()); + addFieldType(menu, boost::make_shared<QtVCardTitleField::FieldInfo>()); + addFieldType(menu, boost::make_shared<QtVCardOrganisationField::FieldInfo>()); + addFieldType(menu, boost::make_shared<QtVCardURLField::FieldInfo>()); + addFieldType(menu, boost::make_shared<QtVCardDescriptionField::FieldInfo>()); + addFieldType(menu, boost::make_shared<QtVCardAddressLabelField::FieldInfo>()); + + setEditable(false); +} + +QtVCardWidget::~QtVCardWidget() { + delete ui; +} + +bool QtVCardWidget::isEditable() const { + return editable; +} + +void QtVCardWidget::setEditable(bool editable) { + this->editable = editable; + + ui->photoAndName->setProperty("editable", QVariant(editable)); + //ui->photoAndName->setStyleSheet(editable ? "" : "background: transparent;"); + + for(int n = 0; n < ui->cardFields->count(); n++) { + QWidget* widget = ui->cardFields->itemAt(n)->widget(); + if (!widget) continue; + if (widget->property("editable").isValid()) { + widget->setProperty("editable", QVariant(editable)); + //widget->setStyleSheet(editable ? "" : "background: transparent;"); + } + } + if (editable) { + ui->toolButton->show(); + if ((findChild<QtVCardBirthdayField*>() == 0)) { + } + } else { + ui->toolButton->hide(); + } + + editableChanged(editable); +} + +void QtVCardWidget::setVCard(VCard::ref vcard) { + SWIFT_LOG(debug) << std::endl; + clearFields(); + this->vcard = vcard; + ui->photoAndName->setFormattedName(P2QSTRING(vcard->getFullName())); + ui->photoAndName->setNickname(P2QSTRING(vcard->getNickname())); + ui->photoAndName->setPrefix(P2QSTRING(vcard->getPrefix())); + ui->photoAndName->setGivenName(P2QSTRING(vcard->getGivenName())); + ui->photoAndName->setMiddleName(P2QSTRING(vcard->getMiddleName())); + ui->photoAndName->setFamilyName(P2QSTRING(vcard->getFamilyName())); + ui->photoAndName->setSuffix(P2QSTRING(vcard->getSuffix())); + ui->photoAndName->setAvatar(vcard->getPhoto(), vcard->getPhotoType()); + + foreach (const VCard::EMailAddress& address, vcard->getEMailAddresses()) { + QtVCardEMailField* emailField = new QtVCardEMailField(this); + emailField->setAddress(P2QSTRING(address.address)); + emailField->setType(address.isX400 ? QtVCardEMailField::X_400 : QtVCardEMailField::Internet); + emailField->setWork(address.isWork); + emailField->setHome(address.isHome); + emailField->setPreferred(address.isPreferred); + ui->cardFields->insertWidget(ui->cardFields->count(), emailField); + } + + if (!vcard->getBirthday().is_not_a_date_time()) { + QtVCardBirthdayField* bdayField = new QtVCardBirthdayField(this); + bdayField->setBirthday(B2QDATE(vcard->getBirthday()).date()); + ui->cardFields->insertWidget(ui->cardFields->count(), bdayField); + } + + foreach (const JID& jid, vcard->getJIDs()) { + QtVCardJIDField* jidField = new QtVCardJIDField(this); + jidField->setJID(P2QSTRING(jid.toString())); + ui->cardFields->insertWidget(ui->cardFields->count(), jidField); + } + + foreach (const std::string& url, vcard->getURLs()) { + QtVCardURLField* urlField = new QtVCardURLField(this); + urlField->setURL(P2QSTRING(url)); + ui->cardFields->insertWidget(ui->cardFields->count(), urlField); + } + + foreach (const VCard::Telephone& telephone, vcard->getTelephones()) { + QtVCardTelephoneField* telField = new QtVCardTelephoneField(this); + telField->setNumber(P2QSTRING(telephone.number)); + telField->setHome(telephone.isHome); + telField->setWork(telephone.isWork); + telField->setVoice(telephone.isVoice); + telField->setFax(telephone.isFax); + telField->setPager(telephone.isPager); + telField->setMSG(telephone.isMSG); + telField->setCell(telephone.isCell); + telField->setVideo(telephone.isVideo); + telField->setBBS(telephone.isBBS); + telField->setModem(telephone.isModem); + telField->setISDN(telephone.isISDN); + telField->setPCS(telephone.isPCS); + telField->setPreferred(telephone.isPreferred); + ui->cardFields->insertWidget(ui->cardFields->count(), telField); + } + + if (!vcard->getDescription().empty()) { + QtVCardDescriptionField* descriptionField = new QtVCardDescriptionField(this); + descriptionField->setDescription(P2QSTRING(vcard->getDescription())); + ui->cardFields->insertWidget(ui->cardFields->count(), descriptionField); + } + + foreach (const std::string& role, vcard->getRoles()) { + QtVCardRoleField* roleField = new QtVCardRoleField(this); + roleField->setRole(P2QSTRING(role)); + ui->cardFields->insertWidget(ui->cardFields->count(), roleField); + } + + foreach (const std::string& title, vcard->getTitles()) { + QtVCardTitleField* titleField = new QtVCardTitleField(this); + titleField->setTitle(P2QSTRING(title)); + ui->cardFields->insertWidget(ui->cardFields->count(), titleField); + } + + foreach (const VCard::Organization organisation, vcard->getOrganizations()) { + QtVCardOrganisationField* organisationField = new QtVCardOrganisationField(this); + organisationField->setName(P2QSTRING(organisation.name)); + + QList<QString> units; + foreach(const std::string& unit, organisation.units) { + units.push_back(P2QSTRING(unit)); + } + organisationField->setUnits(units); + ui->cardFields->insertWidget(ui->cardFields->count(), organisationField); + } + + foreach (const VCard::Address& address, vcard->getAddresses()) { + QtVCardAddressField* addressField = new QtVCardAddressField(this); + addressField->setHome(address.isHome); + addressField->setWork(address.isWork); + addressField->setPostal(address.isPostal); + addressField->setParcel(address.isParcel); + addressField->setDeliveryType(address.deliveryType == VCard::InternationalDelivery ? QtVCardAddressField::InternationalDelivery : QtVCardAddressField::DomesticDelivery); + addressField->setPreferred(address.isPreferred); + + addressField->setPOBox(P2QSTRING(address.POBox)); + addressField->setAddressExtension(P2QSTRING(address.addressExtension)); + addressField->setStreet(P2QSTRING(address.street)); + addressField->setLocality(P2QSTRING(address.locality)); + addressField->setRegion(P2QSTRING(address.region)); + addressField->setPostalCode(P2QSTRING(address.postalCode)); + addressField->setCountry(P2QSTRING(address.country)); + + ui->cardFields->insertWidget(ui->cardFields->count(), addressField); + } + + foreach (const VCard::AddressLabel& addressLabel, vcard->getAddressLabels()) { + QtVCardAddressLabelField* addressLabelField = new QtVCardAddressLabelField(this); + addressLabelField->setHome(addressLabel.isHome); + addressLabelField->setWork(addressLabel.isWork); + addressLabelField->setPostal(addressLabel.isPostal); + addressLabelField->setParcel(addressLabel.isParcel); + addressLabelField->setDeliveryType(addressLabel.deliveryType == VCard::InternationalDelivery ? QtVCardAddressLabelField::InternationalDelivery : QtVCardAddressLabelField::DomesticDelivery); + addressLabelField->setPreferred(addressLabel.isPreferred); + + std::string joinedLines = boost::algorithm::join(addressLabel.lines, "\n"); + addressLabelField->setLines(P2QSTRING(joinedLines)); + + ui->cardFields->insertWidget(ui->cardFields->count(), addressLabelField); + } + + setEditable(editable); +} + +VCard::ref QtVCardWidget::getVCard() { + SWIFT_LOG(debug) << std::endl; + clearEmptyFields(); + vcard->setFullName(Q2PSTRING(ui->photoAndName->getFormattedName())); + vcard->setNickname(Q2PSTRING(ui->photoAndName->getNickname())); + vcard->setPrefix(Q2PSTRING(ui->photoAndName->getPrefix())); + vcard->setGivenName(Q2PSTRING(ui->photoAndName->getGivenName())); + vcard->setMiddleName(Q2PSTRING(ui->photoAndName->getMiddleName())); + vcard->setFamilyName(Q2PSTRING(ui->photoAndName->getFamilyName())); + vcard->setSuffix(Q2PSTRING(ui->photoAndName->getSuffix())); + vcard->setPhoto(ui->photoAndName->getAvatarData()); + vcard->setPhotoType(ui->photoAndName->getAvatarType()); + + vcard->clearEMailAddresses(); + vcard->clearJIDs(); + vcard->clearURLs(); + vcard->clearTelephones(); + vcard->clearRoles(); + vcard->clearTitles(); + vcard->clearOrganizations(); + vcard->clearAddresses(); + vcard->clearAddressLabels(); + + QtVCardBirthdayField* bdayField = NULL; + QtVCardDescriptionField* descriptionField = NULL; + for(int n = 0; n < ui->cardFields->count(); n++) { + QWidget* widget = ui->cardFields->itemAt(n)->widget(); + + QtVCardEMailField* emailField; + if ((emailField = dynamic_cast<QtVCardEMailField*>(widget))) { + VCard::EMailAddress address; + address.address = Q2PSTRING(emailField->getAddress()); + address.isInternet = emailField->getType() == QtVCardEMailField::Internet; + address.isX400 = emailField->getType() == QtVCardEMailField::X_400; + address.isHome = emailField->getHome(); + address.isWork = emailField->getWork(); + address.isPreferred = emailField->getPreferred(); + vcard->addEMailAddress(address); + continue; + } + + QtVCardJIDField* jidField; + if ((jidField = dynamic_cast<QtVCardJIDField*>(widget))) { + JID jid(Q2PSTRING(jidField->getJID())); + if (jid.isValid()) { + vcard->addJID(jid); + } + continue; + } + + QtVCardURLField* urlField; + if ((urlField = dynamic_cast<QtVCardURLField*>(widget))) { + vcard->addURL(Q2PSTRING(urlField->getURL())); + continue; + } + + QtVCardTelephoneField* telephoneField; + if ((telephoneField = dynamic_cast<QtVCardTelephoneField*>(widget))) { + VCard::Telephone telephone; + telephone.number = Q2PSTRING(telephoneField->getNumber()); + telephone.isHome = telephoneField->getHome(); + telephone.isWork = telephoneField->getWork(); + telephone.isVoice = telephoneField->getVoice(); + telephone.isFax = telephoneField->getFax(); + telephone.isPager = telephoneField->getPager(); + telephone.isMSG = telephoneField->getMSG(); + telephone.isCell = telephoneField->getCell(); + telephone.isVideo = telephoneField->getVideo(); + telephone.isBBS = telephoneField->getBBS(); + telephone.isModem = telephoneField->getModem(); + telephone.isISDN = telephoneField->getISDN(); + telephone.isPCS = telephoneField->getPCS(); + telephone.isPreferred = telephoneField->getPreferred(); + vcard->addTelephone(telephone); + continue; + } + + if (dynamic_cast<QtVCardBirthdayField*>(widget)) { + bdayField = dynamic_cast<QtVCardBirthdayField*>(widget); + continue; + } + + if (dynamic_cast<QtVCardDescriptionField*>(widget)) { + descriptionField = dynamic_cast<QtVCardDescriptionField*>(widget); + continue; + } + + QtVCardRoleField* roleField; + if ((roleField = dynamic_cast<QtVCardRoleField*>(widget))) { + vcard->addRole(Q2PSTRING(roleField->getRole())); + continue; + } + + QtVCardTitleField* titleField; + if ((titleField = dynamic_cast<QtVCardTitleField*>(widget))) { + vcard->addTitle(Q2PSTRING(titleField->getTitle())); + continue; + } + + QtVCardOrganisationField* organisationField; + if ((organisationField = dynamic_cast<QtVCardOrganisationField*>(widget))) { + VCard::Organization organisation; + organisation.name = Q2PSTRING(organisationField->getName()); + foreach(const QString &unit, organisationField->getUnits()) { + organisation.units.push_back(Q2PSTRING(unit)); + } + vcard->addOrganization(organisation); + continue; + } + + QtVCardAddressField* addressField; + if ((addressField = dynamic_cast<QtVCardAddressField*>(widget))) { + VCard::Address address; + address.isHome = addressField->getHome(); + address.isWork = addressField->getWork(); + address.isPostal = addressField->getPostal(); + address.isParcel = addressField->getParcel(); + address.deliveryType = addressField->getDeliveryType() == QtVCardAddressField::InternationalDelivery ? VCard::InternationalDelivery : VCard::DomesticDelivery; + address.isPreferred = addressField->getPreferred(); + + address.POBox = Q2PSTRING(addressField->getPOBox()); + address.addressExtension = Q2PSTRING(addressField->getAddressExtension()); + address.street = Q2PSTRING(addressField->getStreet()); + address.locality = Q2PSTRING(addressField->getLocality()); + address.region = Q2PSTRING(addressField->getRegion()); + address.postalCode = Q2PSTRING(addressField->getPostalCode()); + address.country = Q2PSTRING(addressField->getCountry()); + vcard->addAddress(address); + continue; + } + + QtVCardAddressLabelField* addressLabelField; + if ((addressLabelField = dynamic_cast<QtVCardAddressLabelField*>(widget))) { + VCard::AddressLabel addressLabel; + addressLabel.isHome = addressLabelField->getHome(); + addressLabel.isWork = addressLabelField->getWork(); + addressLabel.isPostal = addressLabelField->getPostal(); + addressLabel.isParcel = addressLabelField->getParcel(); + addressLabel.deliveryType = addressLabelField->getDeliveryType() == QtVCardAddressLabelField::InternationalDelivery ? VCard::InternationalDelivery : VCard::DomesticDelivery; + addressLabel.isPreferred = addressLabelField->getPreferred(); + + std::string lines = Q2PSTRING(addressLabelField->getLines()); + boost::split(addressLabel.lines,lines, boost::is_any_of("\n")); + + vcard->addAddressLabel(addressLabel); + continue; + } + } + + if (bdayField) { + vcard->setBirthday(boost::posix_time::from_time_t(QDateTime(bdayField->getBirthday()).toTime_t())); + } else { + vcard->setBirthday(boost::posix_time::ptime()); + } + + if (descriptionField) { + vcard->setDescription(Q2PSTRING(descriptionField->getDescription())); + } else { + vcard->setDescription(""); + } + + return vcard; +} + +void QtVCardWidget::addField() { + QAction* action = NULL; + if ((action = dynamic_cast<QAction*>(sender()))) { + boost::shared_ptr<QtVCardFieldInfo> fieldInfo = actionFieldInfo[action]; + ui->cardFields->insertWidget(ui->cardFields->count(), fieldInfo->createFieldInstance(this, true)); + } +} + +void QtVCardWidget::addFieldType(QMenu* menu, boost::shared_ptr<QtVCardFieldInfo> fieldType) { + QAction* action = new QAction(tr("Add ") + fieldType->getMenuName(), this); + actionFieldInfo[action] = fieldType; + connect(action, SIGNAL(triggered()), this, SLOT(addField())); + menu->addAction(action); +} + +int QtVCardWidget::fieldTypeInstances(boost::shared_ptr<QtVCardFieldInfo> fieldType) { + int instances = 0; + for (int n = 0; n < ui->cardFields->count(); n++) { + if (fieldType->testInstance(ui->cardFields->itemAt(n)->widget())) instances++; + } + return instances; +} + +void QtVCardWidget::clearFields() { + assert(ui->cardFields->count() >= 0); + while(ui->cardFields->count() > 0) { + QLayoutItem* child; + if ((child = ui->cardFields->takeAt(0)) != 0) { + delete child->widget(); + delete child; + } + } +} + +void QtVCardWidget::clearEmptyFields() { + for (int n = 0; n < ui->cardFields->count(); n++) { + QWidget* field = ui->cardFields->itemAt(n)->widget(); + if (field->property("empty").isValid() && field->property("empty").toBool()) { + ui->cardFields->removeWidget(field); + delete field; + n--; + } + } +} + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardWidget.h b/Swift/QtUI/QtVCardWidget/QtVCardWidget.h new file mode 100644 index 0000000..74850fb --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardWidget.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include <boost/smart_ptr/make_shared.hpp> + +#include "QtVCardFieldInfo.h" +#include "QtVCardPhotoAndNameFields.h" + +#include <Swiften/Elements/VCard.h> + +namespace Ui { + class QtVCardWidget; +} + +namespace Swift { + + class QtVCardWidget : public QWidget { + Q_OBJECT + Q_PROPERTY(bool editable READ isEditable WRITE setEditable) + + public : + explicit QtVCardWidget(QWidget* parent = 0); + ~QtVCardWidget(); + + bool isEditable() const; + void setEditable(bool); + + void setVCard(VCard::ref vcard); + VCard::ref getVCard(); + + signals: + void editableChanged(bool editable); + + private slots: + void addField(); + + private: + void addFieldType(QMenu*, boost::shared_ptr<QtVCardFieldInfo>); + int fieldTypeInstances(boost::shared_ptr<QtVCardFieldInfo>); + void clearFields(); + void clearEmptyFields(); + + private: + VCard::ref vcard; + Ui::QtVCardWidget* ui; + bool editable; + QMenu* menu; + std::map<QAction*, boost::shared_ptr<QtVCardFieldInfo> > actionFieldInfo; + }; + +} diff --git a/Swift/QtUI/QtVCardWidget/QtVCardWidget.ui b/Swift/QtUI/QtVCardWidget/QtVCardWidget.ui new file mode 100644 index 0000000..d005f01 --- /dev/null +++ b/Swift/QtUI/QtVCardWidget/QtVCardWidget.ui @@ -0,0 +1,143 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtVCardWidget</class> + <widget class="QWidget" name="QtVCardWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>535</width> + <height>126</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout" rowstretch="1,0" columnstretch="1,0"> + <property name="margin"> + <number>5</number> + </property> + <item row="0" column="0" colspan="2"> + <layout class="QVBoxLayout" name="card" stretch="0,0,1"> + <property name="spacing"> + <number>2</number> + </property> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + <item> + <widget class="Swift::QtVCardPhotoAndNameFields" name="photoAndName" native="true"/> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QScrollArea" name="scrollArea"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>523</width> + <height>76</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetMinAndMaxSize</enum> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QVBoxLayout" name="cardFields"> + <property name="spacing"> + <number>2</number> + </property> + <property name="margin"> + <number>5</number> + </property> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>1000</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </item> + <item row="1" column="1"> + <widget class="QToolButton" name="toolButton"> + <property name="text"> + <string>Add Field</string> + </property> + <property name="popupMode"> + <enum>QToolButton::InstantPopup</enum> + </property> + <property name="autoRaise"> + <bool>false</bool> + </property> + <property name="arrowType"> + <enum>Qt::NoArrow</enum> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Swift::QtVCardPhotoAndNameFields</class> + <extends>QWidget</extends> + <header>QtVCardPhotoAndNameFields.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/Roster/QtOccupantListWidget.cpp b/Swift/QtUI/Roster/QtOccupantListWidget.cpp index 5d26c46..12dc1e4 100644 --- a/Swift/QtUI/Roster/QtOccupantListWidget.cpp +++ b/Swift/QtUI/Roster/QtOccupantListWidget.cpp @@ -58,6 +58,7 @@ void QtOccupantListWidget::contextMenuEvent(QContextMenuEvent* event) { case ChatWindow::MakeParticipant: text = tr("Make participant"); break; case ChatWindow::MakeVisitor: text = tr("Remove voice"); break; case ChatWindow::AddContact: text = tr("Add to contacts"); break; + case ChatWindow::ShowProfile: text = tr("Show profile"); break; } QAction* action = contextMenu.addAction(text); actions[action] = availableAction; diff --git a/Swift/QtUI/Roster/QtRosterWidget.cpp b/Swift/QtUI/Roster/QtRosterWidget.cpp index 1cf073b..b783ff6 100644 --- a/Swift/QtUI/Roster/QtRosterWidget.cpp +++ b/Swift/QtUI/Roster/QtRosterWidget.cpp @@ -16,6 +16,7 @@ #include "Swift/Controllers/UIEvents/RenameGroupUIEvent.h" #include "Swift/Controllers/UIEvents/SendFileUIEvent.h" #include "Swift/Controllers/UIEvents/RequestWhiteboardUIEvent.h" +#include "Swift/Controllers/UIEvents/ShowProfileForRosterItemUIEvent.h" #include "QtContactEditWindow.h" #include "Swift/Controllers/Roster/ContactRosterItem.h" #include "Swift/Controllers/Roster/GroupRosterItem.h" @@ -57,6 +58,7 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) { if (ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item)) { QAction* editContact = contextMenu.addAction(tr("Edit…")); QAction* removeContact = contextMenu.addAction(tr("Remove")); + QAction* showProfileForContact = contextMenu.addAction(tr("Show Profile")); #ifdef SWIFT_EXPERIMENTAL_FT QAction* sendFile = NULL; if (contact->supportsFeature(ContactRosterItem::FileTransferFeature)) { @@ -78,6 +80,9 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) { eventStream_->send(boost::make_shared<RemoveRosterItemUIEvent>(contact->getJID())); } } + else if (result == showProfileForContact) { + eventStream_->send(boost::make_shared<ShowProfileForRosterItemUIEvent>(contact->getJID())); + } #ifdef SWIFT_EXPERIMENTAL_FT else if (sendFile && result == sendFile) { QString fileName = QFileDialog::getOpenFileName(this, tr("Send File"), "", tr("All Files (*);;")); diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 70a1038..35eda5b 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -164,6 +164,40 @@ sources = [ "QtUISettingConstants.cpp" ] +# QtVCardWidget +sources.extend([ + "QtVCardWidget/QtResizableLineEdit.cpp", + "QtVCardWidget/QtVCardAddressField.cpp", + "QtVCardWidget/QtVCardAddressLabelField.cpp", + "QtVCardWidget/QtVCardBirthdayField.cpp", + "QtVCardWidget/QtVCardDescriptionField.cpp", + "QtVCardWidget/QtVCardEMailField.cpp", + "QtVCardWidget/QtVCardJIDField.cpp", + "QtVCardWidget/QtVCardOrganisationField.cpp", + "QtVCardWidget/QtVCardPhotoAndNameFields.cpp", + "QtVCardWidget/QtVCardRoleField.cpp", + "QtVCardWidget/QtVCardTelephoneField.cpp", + "QtVCardWidget/QtVCardTitleField.cpp", + "QtVCardWidget/QtVCardURLField.cpp", + "QtVCardWidget/QtVCardWidget.cpp" +]) + +myenv.Uic4("QtVCardWidget/QtVCardAddressField.ui") +myenv.Uic4("QtVCardWidget/QtVCardAddressLabelField.ui") +myenv.Uic4("QtVCardWidget/QtVCardBirthdayField.ui") +myenv.Uic4("QtVCardWidget/QtVCardDescriptionField.ui") +myenv.Uic4("QtVCardWidget/QtVCardEMailField.ui") +myenv.Uic4("QtVCardWidget/QtVCardJIDField.ui") +myenv.Uic4("QtVCardWidget/QtVCardOrganisationField.ui") +myenv.Uic4("QtVCardWidget/QtVCardPhotoAndNameFields.ui") +myenv.Uic4("QtVCardWidget/QtVCardRoleField.ui") +myenv.Uic4("QtVCardWidget/QtVCardTelephoneField.ui") +myenv.Uic4("QtVCardWidget/QtVCardTitleField.ui") +myenv.Uic4("QtVCardWidget/QtVCardURLField.ui") +myenv.Uic4("QtVCardWidget/QtVCardWidget.ui") +myenv.Uic4("QtProfileWindow.ui") + + myenv["SWIFT_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "swift") version_match = re.match("(\d+)\.(\d+).*", myenv["SWIFT_VERSION"]) myenv["SWIFT_VERSION_MAJOR"] = int(version_match.group(1)) if version_match else 0 diff --git a/Swiften/Elements/VCard.h b/Swiften/Elements/VCard.h index f9822c9..41f2623 100644 --- a/Swiften/Elements/VCard.h +++ b/Swiften/Elements/VCard.h @@ -7,8 +7,10 @@ #pragma once #include <boost/shared_ptr.hpp> +#include <boost/date_time/posix_time/ptime.hpp> #include <string> +#include <Swiften/JID/JID.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/Elements/Payload.h> @@ -29,6 +31,71 @@ namespace Swift { std::string address; }; + struct Telephone { + Telephone() : isHome(false), isWork(false), isVoice(false), isFax(false), isPager(false), isMSG(false), isCell(false), + isVideo(false), isBBS(false), isModem(false), isISDN(false), isPCS(false), isPreferred(false) { + } + + bool isHome; + bool isWork; + bool isVoice; + bool isFax; + bool isPager; + bool isMSG; + bool isCell; + bool isVideo; + bool isBBS; + bool isModem; + bool isISDN; + bool isPCS; + bool isPreferred; + std::string number; + }; + + enum DeliveryType { + DomesticDelivery, + InternationalDelivery, + None + }; + + struct Address { + Address() : isHome(false), isWork(false), isPostal(false), isParcel(false), deliveryType(None), isPreferred(false) { + } + + bool isHome; + bool isWork; + bool isPostal; + bool isParcel; + DeliveryType deliveryType; + bool isPreferred; + + std::string POBox; + std::string addressExtension; + std::string street; + std::string locality; + std::string region; + std::string postalCode; + std::string country; + }; + + struct AddressLabel { + AddressLabel() : isHome(false), isWork(false), isPostal(false), isParcel(false), deliveryType(None), isPreferred(false) { + } + + bool isHome; + bool isWork; + bool isPostal; + bool isParcel; + DeliveryType deliveryType; + bool isPreferred; + std::vector<std::string> lines; + }; + + struct Organization { + std::string name; + std::vector<std::string> units; + }; + VCard() {} void setVersion(const std::string& version) { version_ = version; } @@ -78,8 +145,124 @@ namespace Swift { emailAddresses_.push_back(email); } + void clearEMailAddresses() { + emailAddresses_.clear(); + } + EMailAddress getPreferredEMailAddress() const; + void setBirthday(const boost::posix_time::ptime& birthday) { + birthday_ = birthday; + } + + const boost::posix_time::ptime& getBirthday() const { + return birthday_; + } + + const std::vector<Telephone>& getTelephones() const { + return telephones_; + } + + void addTelephone(const Telephone& phone) { + telephones_.push_back(phone); + } + + void clearTelephones() { + telephones_.clear(); + } + + const std::vector<Address>& getAddresses() const { + return addresses_; + } + + void addAddress(const Address& address) { + addresses_.push_back(address); + } + + void clearAddresses() { + addresses_.clear(); + } + + const std::vector<AddressLabel>& getAddressLabels() const { + return addressLabels_; + } + + void addAddressLabel(const AddressLabel& addressLabel) { + addressLabels_.push_back(addressLabel); + } + + void clearAddressLabels() { + addressLabels_.clear(); + } + + const std::vector<JID>& getJIDs() const { + return jids_; + } + + void addJID(const JID& jid) { + jids_.push_back(jid); + } + + void clearJIDs() { + jids_.clear(); + } + + const std::string& getDescription() const { + return description_; + } + + void setDescription(const std::string& description) { + this->description_ = description; + } + + const std::vector<Organization>& getOrganizations() const { + return organizations_; + } + + void addOrganization(const Organization& organization) { + organizations_.push_back(organization); + } + + void clearOrganizations() { + organizations_.clear(); + } + + const std::vector<std::string>& getTitles() const { + return titles_; + } + + void addTitle(const std::string& title) { + titles_.push_back(title); + } + + void clearTitles() { + titles_.clear(); + } + + const std::vector<std::string>& getRoles() const { + return roles_; + } + + void addRole(const std::string& role) { + roles_.push_back(role); + } + + void clearRoles() { + roles_.clear(); + } + + const std::vector<std::string>& getURLs() const { + return urls_; + } + + void addURL(const std::string& url) { + urls_.push_back(url); + } + + void clearURLs() { + urls_.clear(); + } + private: std::string version_; std::string fullName_; @@ -92,7 +275,17 @@ namespace Swift { ByteArray photo_; std::string photoType_; std::string nick_; + boost::posix_time::ptime birthday_; std::string unknownContent_; std::vector<EMailAddress> emailAddresses_; + std::vector<Telephone> telephones_; + std::vector<Address> addresses_; + std::vector<AddressLabel> addressLabels_; + std::vector<JID> jids_; + std::string description_; + std::vector<Organization> organizations_; + std::vector<std::string> titles_; + std::vector<std::string> roles_; + std::vector<std::string> urls_; }; } diff --git a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp index f1e6635..eda2547 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp @@ -7,6 +7,8 @@ #include <Swiften/Base/ByteArray.h> #include <QA/Checker/IO.h> +#include <boost/date_time/posix_time/posix_time.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -48,8 +50,36 @@ class VCardParserTest : public CppUnit::TestFixture { "<WORK/>" "<X400/>" "</EMAIL>" + "<TEL>" + "<NUMBER>555-6273</NUMBER>" + "<HOME/>" + "<VOICE/>" + "</TEL>" + "<ADR>" + "<LOCALITY>Any Town</LOCALITY>" + "<STREET>Fake Street 123</STREET>" + "<PCODE>12345</PCODE>" + "<CTRY>USA</CTRY>" + "<HOME/>" + "</ADR>" + "<LABEL>" + "<LINE>Fake Street 123</LINE>" + "<LINE>12345 Any Town</LINE>" + "<LINE>USA</LINE>" + "<HOME/>" + "</LABEL>" "<NICKNAME>DreamGirl</NICKNAME>" - "<BDAY>1234</BDAY>" + "<BDAY>1865-05-04</BDAY>" + "<JID>alice@teaparty.lit</JID>" + "<JID>alice@wonderland.lit</JID>" + "<DESC>I once fell down a rabbit hole.</DESC>" + "<ORG>" + "<ORGNAME>Alice In Wonderland Inc.</ORGNAME>" + "</ORG>" + "<TITLE>Some Title</TITLE>" + "<ROLE>Main Character</ROLE>" + "<URL>http://wonderland.lit/~alice</URL>" + "<URL>http://teaparty.lit/~alice2</URL>" "<MAILER>mutt</MAILER>" "</vCard>")); @@ -62,7 +92,7 @@ class VCardParserTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(std::string("Mrs"), payload->getPrefix()); CPPUNIT_ASSERT_EQUAL(std::string("PhD"), payload->getSuffix()); CPPUNIT_ASSERT_EQUAL(std::string("DreamGirl"), payload->getNickname()); - CPPUNIT_ASSERT_EQUAL(std::string("<BDAY xmlns=\"vcard-temp\">1234</BDAY><MAILER xmlns=\"vcard-temp\">mutt</MAILER>"), payload->getUnknownContent()); + CPPUNIT_ASSERT_EQUAL(boost::posix_time::ptime(boost::gregorian::date(1865, 5, 4)), payload->getBirthday()); CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getEMailAddresses().size())); CPPUNIT_ASSERT_EQUAL(std::string("alice@wonderland.lit"), payload->getEMailAddresses()[0].address); CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isHome); @@ -76,6 +106,45 @@ class VCardParserTest : public CppUnit::TestFixture { CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isPreferred); CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isWork); CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isX400); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getTelephones().size())); + CPPUNIT_ASSERT_EQUAL(std::string("555-6273"), payload->getTelephones()[0].number); + CPPUNIT_ASSERT(payload->getTelephones()[0].isHome); + CPPUNIT_ASSERT(payload->getTelephones()[0].isVoice); + CPPUNIT_ASSERT(!payload->getTelephones()[0].isPreferred); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getAddresses().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Any Town"), payload->getAddresses()[0].locality); + CPPUNIT_ASSERT_EQUAL(std::string("Fake Street 123"), payload->getAddresses()[0].street); + CPPUNIT_ASSERT_EQUAL(std::string("12345"), payload->getAddresses()[0].postalCode); + CPPUNIT_ASSERT_EQUAL(std::string("USA"), payload->getAddresses()[0].country); + CPPUNIT_ASSERT(payload->getAddresses()[0].isHome); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getAddressLabels().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Fake Street 123"), payload->getAddressLabels()[0].lines[0]); + CPPUNIT_ASSERT_EQUAL(std::string("12345 Any Town"), payload->getAddressLabels()[0].lines[1]); + CPPUNIT_ASSERT_EQUAL(std::string("USA"), payload->getAddressLabels()[0].lines[2]); + CPPUNIT_ASSERT(payload->getAddressLabels()[0].isHome); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getJIDs().size())); + CPPUNIT_ASSERT_EQUAL(JID("alice@teaparty.lit"), payload->getJIDs()[0]); + CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit"), payload->getJIDs()[1]); + + CPPUNIT_ASSERT_EQUAL(std::string("I once fell down a rabbit hole."), payload->getDescription()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getOrganizations().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Alice In Wonderland Inc."), payload->getOrganizations()[0].name); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(payload->getOrganizations()[0].units.size())); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getTitles().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Some Title"), payload->getTitles()[0]); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getRoles().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Main Character"), payload->getRoles()[0]); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getURLs().size())); + CPPUNIT_ASSERT_EQUAL(std::string("http://wonderland.lit/~alice"), payload->getURLs()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("http://teaparty.lit/~alice2"), payload->getURLs()[1]); + + CPPUNIT_ASSERT_EQUAL(std::string("<MAILER xmlns=\"vcard-temp\">mutt</MAILER>"), payload->getUnknownContent()); } void testParse_Photo() { diff --git a/Swiften/Parser/PayloadParsers/VCardParser.cpp b/Swiften/Parser/PayloadParsers/VCardParser.cpp index 553d26a..9640787 100644 --- a/Swiften/Parser/PayloadParsers/VCardParser.cpp +++ b/Swiften/Parser/PayloadParsers/VCardParser.cpp @@ -6,6 +6,7 @@ #include <Swiften/Parser/PayloadParsers/VCardParser.h> #include <Swiften/Base/foreach.h> +#include <Swiften/Base/DateTime.h> #include <Swiften/StringCodecs/Base64.h> #include <Swiften/Parser/SerializingParser.h> @@ -20,6 +21,18 @@ void VCardParser::handleStartElement(const std::string& element, const std::stri if (elementHierarchy == "/vCard/EMAIL") { currentEMailAddress_ = VCard::EMailAddress(); } + if (elementHierarchy == "/vCard/TEL") { + currentTelephone_ = VCard::Telephone(); + } + if (elementHierarchy == "/vCard/ADR") { + currentAddress_ = VCard::Address(); + } + if (elementHierarchy == "/vCard/LABEL") { + currentAddressLabel_ = VCard::AddressLabel(); + } + if (elementHierarchy == "/vCard/ORG") { + currentOrganization_ = VCard::Organization(); + } if (elementStack_.size() == 2) { assert(!unknownContentParser_); unknownContentParser_ = new SerializingParser(); @@ -90,9 +103,160 @@ void VCardParser::handleEndElement(const std::string& element, const std::string else if (elementHierarchy == "/vCard/EMAIL/PREF") { currentEMailAddress_.isPreferred = true; } - else if (elementHierarchy == "/vCard/EMAIL") { + else if (elementHierarchy == "/vCard/EMAIL" && !currentEMailAddress_.address.empty()) { getPayloadInternal()->addEMailAddress(currentEMailAddress_); } + else if (elementHierarchy == "/vCard/BDAY" && !currentText_.empty()) { + getPayloadInternal()->setBirthday(stringToDateTime(currentText_)); + } + else if (elementHierarchy == "/vCard/TEL/NUMBER") { + currentTelephone_.number = currentText_; + } + else if (elementHierarchy == "/vCard/TEL/HOME") { + currentTelephone_.isHome = true; + } + else if (elementHierarchy == "/vCard/TEL/WORK") { + currentTelephone_.isWork = true; + } + else if (elementHierarchy == "/vCard/TEL/VOICE") { + currentTelephone_.isVoice = true; + } + else if (elementHierarchy == "/vCard/TEL/FAX") { + currentTelephone_.isFax = true; + } + else if (elementHierarchy == "/vCard/TEL/PAGER") { + currentTelephone_.isPager = true; + } + else if (elementHierarchy == "/vCard/TEL/MSG") { + currentTelephone_.isMSG = true; + } + else if (elementHierarchy == "/vCard/TEL/CELL") { + currentTelephone_.isCell = true; + } + else if (elementHierarchy == "/vCard/TEL/VIDEO") { + currentTelephone_.isVideo = true; + } + else if (elementHierarchy == "/vCard/TEL/BBS") { + currentTelephone_.isBBS = true; + } + else if (elementHierarchy == "/vCard/TEL/MODEM") { + currentTelephone_.isModem = true; + } + else if (elementHierarchy == "/vCard/TEL/ISDN") { + currentTelephone_.isISDN = true; + } + else if (elementHierarchy == "/vCard/TEL/PCS") { + currentTelephone_.isPCS = true; + } + else if (elementHierarchy == "/vCard/TEL/PREF") { + currentTelephone_.isPreferred = true; + } + else if (elementHierarchy == "/vCard/TEL" && !currentTelephone_.number.empty()) { + getPayloadInternal()->addTelephone(currentTelephone_); + } + else if (elementHierarchy == "/vCard/ADR/HOME") { + currentAddress_.isHome = true; + } + else if (elementHierarchy == "/vCard/ADR/WORK") { + currentAddress_.isWork = true; + } + else if (elementHierarchy == "/vCard/ADR/POSTAL") { + currentAddress_.isPostal = true; + } + else if (elementHierarchy == "/vCard/ADR/PARCEL") { + currentAddress_.isParcel = true; + } + else if (elementHierarchy == "/vCard/ADR/DOM") { + currentAddress_.deliveryType = VCard::DomesticDelivery; + } + else if (elementHierarchy == "/vCard/ADR/INTL") { + currentAddress_.deliveryType = VCard::InternationalDelivery; + } + else if (elementHierarchy == "/vCard/ADR/PREF") { + currentAddress_.isPreferred = true; + } + else if (elementHierarchy == "/vCard/ADR/POBOX") { + currentAddress_.POBox = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/EXTADD") { + currentAddress_.addressExtension = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/STREET") { + currentAddress_.street = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/LOCALITY") { + currentAddress_.locality = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/REGION") { + currentAddress_.region = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/PCODE") { + currentAddress_.postalCode = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/CTRY") { + currentAddress_.country = currentText_; + } + else if (elementHierarchy == "/vCard/ADR") { + if (!currentAddress_.POBox.empty() || !currentAddress_.addressExtension.empty() || + !currentAddress_.street.empty() || !currentAddress_.locality.empty() || + !currentAddress_.region.empty() || !currentAddress_.region.empty() || + !currentAddress_.postalCode.empty() || !currentAddress_.country.empty()) { + getPayloadInternal()->addAddress(currentAddress_); + } + } + else if (elementHierarchy == "/vCard/LABEL/HOME") { + currentAddressLabel_.isHome = true; + } + else if (elementHierarchy == "/vCard/LABEL/WORK") { + currentAddressLabel_.isWork = true; + } + else if (elementHierarchy == "/vCard/LABEL/POSTAL") { + currentAddressLabel_.isPostal = true; + } + else if (elementHierarchy == "/vCard/LABEL/PARCEL") { + currentAddressLabel_.isParcel = true; + } + else if (elementHierarchy == "/vCard/LABEL/DOM") { + currentAddressLabel_.deliveryType = VCard::DomesticDelivery; + } + else if (elementHierarchy == "/vCard/LABEL/INTL") { + currentAddressLabel_.deliveryType = VCard::InternationalDelivery; + } + else if (elementHierarchy == "/vCard/LABEL/PREF") { + currentAddressLabel_.isPreferred = true; + } + else if (elementHierarchy == "/vCard/LABEL/LINE") { + currentAddressLabel_.lines.push_back(currentText_); + } + else if (elementHierarchy == "/vCard/LABEL") { + getPayloadInternal()->addAddressLabel(currentAddressLabel_); + } + else if (elementHierarchy == "/vCard/JID" && !currentText_.empty()) { + getPayloadInternal()->addJID(JID(currentText_)); + } + else if (elementHierarchy == "/vCard/DESC") { + getPayloadInternal()->setDescription(currentText_); + } + else if (elementHierarchy == "/vCard/ORG/ORGNAME") { + currentOrganization_.name = currentText_; + } + else if (elementHierarchy == "/vCard/ORG/ORGUNIT" && !currentText_.empty()) { + currentOrganization_.units.push_back(currentText_); + } + else if (elementHierarchy == "/vCard/ORG") { + if (!currentOrganization_.name.empty() || !currentOrganization_.units.empty()) { + getPayloadInternal()->addOrganization(currentOrganization_); + } + } + else if (elementHierarchy == "/vCard/TITLE" && !currentText_.empty()) { + getPayloadInternal()->addTitle(currentText_); + } + else if (elementHierarchy == "/vCard/ROLE" && !currentText_.empty()) { + getPayloadInternal()->addRole(currentText_); + } + else if (elementHierarchy == "/vCard/URL" && !currentText_.empty()) { + getPayloadInternal()->addURL(currentText_); + } else if (elementStack_.size() == 2 && unknownContentParser_) { getPayloadInternal()->addUnknownContent(unknownContentParser_->getResult()); } diff --git a/Swiften/Parser/PayloadParsers/VCardParser.h b/Swiften/Parser/PayloadParsers/VCardParser.h index b1c47a3..f10d639 100644 --- a/Swiften/Parser/PayloadParsers/VCardParser.h +++ b/Swiften/Parser/PayloadParsers/VCardParser.h @@ -28,6 +28,10 @@ namespace Swift { private: std::vector<std::string> elementStack_; VCard::EMailAddress currentEMailAddress_; + VCard::Telephone currentTelephone_; + VCard::Address currentAddress_; + VCard::AddressLabel currentAddressLabel_; + VCard::Organization currentOrganization_; SerializingParser* unknownContentParser_; std::string currentText_; }; diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp index 3ac1d77..01c8e77 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp @@ -31,14 +31,15 @@ class VCardSerializerTest : public CppUnit::TestFixture vcard->setNickname("DreamGirl"); vcard->setPhoto(createByteArray("abcdef")); vcard->setPhotoType("image/png"); - vcard->addUnknownContent("<BDAY>1234</BDAY><MAILER>mutt</MAILER>"); + vcard->setBirthday(boost::posix_time::ptime(boost::gregorian::date(1865, 5, 4))); + vcard->addUnknownContent("<MAILER>mutt</MAILER>"); - VCard::EMailAddress address1; - address1.address = "alice@wonderland.lit"; - address1.isHome = true; - address1.isPreferred = true; - address1.isInternet = true; - vcard->addEMailAddress(address1); + VCard::EMailAddress emailAddress1; + emailAddress1.address = "alice@wonderland.lit"; + emailAddress1.isHome = true; + emailAddress1.isPreferred = true; + emailAddress1.isInternet = true; + vcard->addEMailAddress(emailAddress1); VCard::EMailAddress address2; address2.address = "alice@teaparty.lit"; @@ -46,6 +47,41 @@ class VCardSerializerTest : public CppUnit::TestFixture address2.isX400 = true; vcard->addEMailAddress(address2); + VCard::Telephone telephone1; + telephone1.number = "555-6273"; + telephone1.isHome = true; + telephone1.isVoice = true; + vcard->addTelephone(telephone1); + + VCard::Address address1; + address1.locality = "Any Town"; + address1.street = "Fake Street 123"; + address1.postalCode = "12345"; + address1.country = "USA"; + address1.isHome = true; + vcard->addAddress(address1); + + VCard::AddressLabel label1; + label1.lines.push_back("Fake Street 123"); + label1.lines.push_back("12345 Any Town"); + label1.lines.push_back("USA"); + label1.isHome = true; + vcard->addAddressLabel(label1); + + vcard->addJID(JID("alice@teaparty.lit")); + vcard->addJID(JID("alice@wonderland.lit")); + + vcard->setDescription("I once fell down a rabbit hole."); + + VCard::Organization org1; + org1.name = "Alice In Wonderland Inc."; + vcard->addOrganization(org1); + + vcard->addTitle("Some Title"); + vcard->addRole("Main Character"); + vcard->addURL("http://wonderland.lit/~alice"); + vcard->addURL("http://teaparty.lit/~alice2"); + std::string expectedResult = "<vCard xmlns=\"vcard-temp\">" "<VERSION>2.0</VERSION>" @@ -73,7 +109,35 @@ class VCardSerializerTest : public CppUnit::TestFixture "<TYPE>image/png</TYPE>" "<BINVAL>YWJjZGVm</BINVAL>" "</PHOTO>" - "<BDAY>1234</BDAY>" + "<BDAY>1865-05-04T00:00:00Z</BDAY>" + "<TEL>" + "<NUMBER>555-6273</NUMBER>" + "<HOME/>" + "<VOICE/>" + "</TEL>" + "<ADR>" + "<STREET>Fake Street 123</STREET>" + "<LOCALITY>Any Town</LOCALITY>" + "<PCODE>12345</PCODE>" + "<CTRY>USA</CTRY>" + "<HOME/>" + "</ADR>" + "<LABEL>" + "<LINE>Fake Street 123</LINE>" + "<LINE>12345 Any Town</LINE>" + "<LINE>USA</LINE>" + "<HOME/>" + "</LABEL>" + "<JID>alice@teaparty.lit</JID>" + "<JID>alice@wonderland.lit</JID>" + "<DESC>I once fell down a rabbit hole.</DESC>" + "<ORG>" + "<ORGNAME>Alice In Wonderland Inc.</ORGNAME>" + "</ORG>" + "<TITLE>Some Title</TITLE>" + "<ROLE>Main Character</ROLE>" + "<URL>http://wonderland.lit/~alice</URL>" + "<URL>http://teaparty.lit/~alice2</URL>" "<MAILER>mutt</MAILER>" "</vCard>"; diff --git a/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp b/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp index 1512c6c..2676a02 100644 --- a/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp @@ -13,10 +13,17 @@ #include <Swiften/Serializer/XML/XMLTextNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> #include <Swiften/StringCodecs/Base64.h> +#include <Swiften/Base/DateTime.h> #include <Swiften/Base/foreach.h> namespace Swift { +boost::shared_ptr<XMLElement> createTextElement(const std::string& elementName, const std::string& text) { + boost::shared_ptr<XMLElement> element = boost::make_shared<XMLElement>(elementName); + element->addNode(boost::make_shared<XMLTextNode>(text)); + return element; +} + VCardSerializer::VCardSerializer() : GenericPayloadSerializer<VCard>() { } @@ -102,6 +109,171 @@ std::string VCardSerializer::serializePayload(boost::shared_ptr<VCard> vcard) c } queryElement.addNode(photoElement); } + if (!vcard->getBirthday().is_not_a_date_time()) { + XMLElement::ref bdayElement(new XMLElement("BDAY")); + bdayElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(dateTimeToString(vcard->getBirthday())))); + queryElement.addNode(bdayElement); + } + + foreach(const VCard::Telephone& telephone, vcard->getTelephones()) { + boost::shared_ptr<XMLElement> telElement(new XMLElement("TEL")); + boost::shared_ptr<XMLElement> numberElement(new XMLElement("NUMBER")); + numberElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(telephone.number))); + telElement->addNode(numberElement); + if (telephone.isHome) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("HOME"))); + } + if (telephone.isWork) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("WORK"))); + } + if (telephone.isVoice) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("VOICE"))); + } + if (telephone.isFax) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("FAX"))); + } + if (telephone.isPager) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("PAGER"))); + } + if (telephone.isMSG) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("MSG"))); + } + if (telephone.isCell) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("CELL"))); + } + if (telephone.isVideo) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("VIDEO"))); + } + if (telephone.isBBS) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("BBS"))); + } + if (telephone.isModem) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("MODEM"))); + } + if (telephone.isISDN) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("ISDN"))); + } + if (telephone.isPCS) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("PCS"))); + } + if (telephone.isPreferred) { + telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("PREF"))); + } + queryElement.addNode(telElement); + } + + foreach(const VCard::Address& address, vcard->getAddresses()) { + boost::shared_ptr<XMLElement> adrElement(new XMLElement("ADR")); + if (!address.POBox.empty()) { + adrElement->addNode(createTextElement("POBOX", address.POBox)); + } + if (!address.addressExtension.empty()) { + adrElement->addNode(createTextElement("EXTADD", address.addressExtension)); + } + if (!address.street.empty()) { + adrElement->addNode(createTextElement("STREET", address.street)); + } + if (!address.locality.empty()) { + adrElement->addNode(createTextElement("LOCALITY", address.locality)); + } + if (!address.region.empty()) { + adrElement->addNode(createTextElement("REGION", address.region)); + } + if (!address.postalCode.empty()) { + adrElement->addNode(createTextElement("PCODE", address.postalCode)); + } + if (!address.country.empty()) { + adrElement->addNode(createTextElement("CTRY", address.country)); + } + + if (address.isHome) { + adrElement->addNode(boost::make_shared<XMLElement>("HOME")); + } + if (address.isWork) { + adrElement->addNode(boost::make_shared<XMLElement>("WORK")); + } + if (address.isPostal) { + adrElement->addNode(boost::make_shared<XMLElement>("POSTAL")); + } + if (address.isParcel) { + adrElement->addNode(boost::make_shared<XMLElement>("PARCEL")); + } + if (address.deliveryType == VCard::DomesticDelivery) { + adrElement->addNode(boost::make_shared<XMLElement>("DOM")); + } + if (address.deliveryType == VCard::InternationalDelivery) { + adrElement->addNode(boost::make_shared<XMLElement>("INTL")); + } + if (address.isPreferred) { + adrElement->addNode(boost::make_shared<XMLElement>("PREF")); + } + queryElement.addNode(adrElement); + } + + foreach(const VCard::AddressLabel& addressLabel, vcard->getAddressLabels()) { + boost::shared_ptr<XMLElement> labelElement(new XMLElement("LABEL")); + + foreach(const std::string& line, addressLabel.lines) { + labelElement->addNode(createTextElement("LINE", line)); + } + + if (addressLabel.isHome) { + labelElement->addNode(boost::make_shared<XMLElement>("HOME")); + } + if (addressLabel.isWork) { + labelElement->addNode(boost::make_shared<XMLElement>("WORK")); + } + if (addressLabel.isPostal) { + labelElement->addNode(boost::make_shared<XMLElement>("POSTAL")); + } + if (addressLabel.isParcel) { + labelElement->addNode(boost::make_shared<XMLElement>("PARCEL")); + } + if (addressLabel.deliveryType == VCard::DomesticDelivery) { + labelElement->addNode(boost::make_shared<XMLElement>("DOM")); + } + if (addressLabel.deliveryType == VCard::InternationalDelivery) { + labelElement->addNode(boost::make_shared<XMLElement>("INTL")); + } + if (addressLabel.isPreferred) { + labelElement->addNode(boost::make_shared<XMLElement>("PREF")); + } + queryElement.addNode(labelElement); + } + + foreach(const JID& jid, vcard->getJIDs()) { + queryElement.addNode(createTextElement("JID", jid.toString())); + } + + if (!vcard->getDescription().empty()) { + queryElement.addNode(createTextElement("DESC", vcard->getDescription())); + } + + foreach(const VCard::Organization& org, vcard->getOrganizations()) { + boost::shared_ptr<XMLElement> orgElement(new XMLElement("ORG")); + if (!org.name.empty()) { + orgElement->addNode(createTextElement("ORGNAME", org.name)); + } + if (!org.units.empty()) { + foreach(const std::string& unit, org.units) { + orgElement->addNode(createTextElement("ORGUNIT", unit)); + } + } + queryElement.addNode(orgElement); + } + + foreach(const std::string& title, vcard->getTitles()) { + queryElement.addNode(createTextElement("TITLE", title)); + } + + foreach(const std::string& role, vcard->getRoles()) { + queryElement.addNode(createTextElement("ROLE", role)); + } + + foreach(const std::string& url, vcard->getURLs()) { + queryElement.addNode(createTextElement("URL", url)); + } + if (!vcard->getUnknownContent().empty()) { queryElement.addNode(boost::make_shared<XMLRawTextNode>(vcard->getUnknownContent())); } |