diff --exclude='*orig' -Naur psi-0.10-test3-orig/src/common.h psi-0.10-test3/src/common.h --- psi-0.10-test3-orig/src/common.h 2005-11-23 20:30:24.000000000 +0000 +++ psi-0.10-test3/src/common.h 2005-11-23 20:40:30.000000000 +0000 @@ -101,6 +101,11 @@ bool oldSmallChats; //Filthy hack, see chat code. int delChats, browser; + + // More properties + QMap contactSoundMsg; + QMap contactPopupAvail; + QMap contactVisible; // Avatars bool avatarsEnabled, avatarsChatdlgEnabled; diff --exclude='*orig' -Naur psi-0.10-test3-orig/src/contactview.cpp psi-0.10-test3/src/contactview.cpp --- psi-0.10-test3-orig/src/contactview.cpp 2005-11-23 20:30:25.000000000 +0000 +++ psi-0.10-test3/src/contactview.cpp 2005-11-23 20:40:30.000000000 +0000 @@ -474,6 +474,12 @@ if(!d->cv->isShowAgents()) return; } + else if (!e->alerting && + option.contactVisible.contains(u.jid().bare()) && + option.contactVisible[u.jid().bare()] != -1) { + if (option.contactVisible[u.jid().bare()] == 0 && !d->cv->isShowHidden()) + return; + } else { if(!e->alerting) { if((!d->cv->isShowOffline() && !u.isAvailable()) || (!d->cv->isShowAway() && u.isAway()) || (!d->cv->isShowHidden() && u.isHidden())) @@ -507,6 +513,12 @@ if(!d->cv->isShowAgents()) delAll = true; } + else if (!e->alerting && + option.contactVisible.contains(u.jid().bare()) && + option.contactVisible[u.jid().bare()] != -1) { + if (option.contactVisible[u.jid().bare()] == 0 && !d->cv->isShowHidden()) + delAll = true; + } else { if(!e->alerting) { if((!d->cv->isShowOffline() && !u.isAvailable()) || (!d->cv->isShowAway() && u.isAway()) || (!d->cv->isShowHidden() && u.isHidden())) @@ -1316,22 +1328,106 @@ pm.insertSeparator(); } + // More properties + QPopupMenu *mm = new QPopupMenu(&pm); + + // Sound notification + { + QPopupMenu *sndm = new QPopupMenu(mm); + sndm->setCheckable(true); + d->cv->qa_contactSoundMsgOn->addTo(sndm); + d->cv->qa_contactSoundMsgOff->addTo(sndm); + d->cv->qa_contactSoundMsgDefault->addTo(sndm); + int n = -1; + if (option.contactSoundMsg.contains(i->u()->jid().bare())) + { + switch (option.contactSoundMsg[i->u()->jid().bare()]) + { + case 1: n = 0; break; + case 0: n = 1; break; + case -1: + default: n = 2; break; + } + } + else + { + n = 2; + } + if (n > -1) sndm->setItemChecked(sndm->idAt(n), true); + mm->insertItem(tr("Message &sounds"), sndm); + } + + // Popup notification for on/offline + { + QPopupMenu *ppm = new QPopupMenu(mm); + ppm->setCheckable(true); + d->cv->qa_contactPopupAvailOn->addTo(ppm); + d->cv->qa_contactPopupAvailOff->addTo(ppm); + d->cv->qa_contactPopupAvailDefault->addTo(ppm); + int n = -1; + if (option.contactPopupAvail.contains(i->u()->jid().bare())) + { + switch (option.contactPopupAvail[i->u()->jid().bare()]) + { + case 1: n = 0; break; + case 0: n = 1; break; + case -1: + default: n = 2; break; + } + } + else + { + n = 2; + } + if (n > -1) ppm->setItemChecked(ppm->idAt(n), true); + mm->insertItem(tr("Availability &popups"), ppm); + } + + // Visibility on roster + { + QPopupMenu *vism = new QPopupMenu(mm); + vism->setCheckable(true); + d->cv->qa_contactVisibleOn->addTo(vism); + d->cv->qa_contactVisibleOff->addTo(vism); + d->cv->qa_contactVisibleDefault->addTo(vism); + int n = -1; + if (option.contactVisible.contains(i->u()->jid().bare())) + { + switch (option.contactVisible[i->u()->jid().bare()]) + { + case 1: n = 0; break; + case 0: n = 1; break; + case -1: + default: n = 2; break; + } + } + else + { + n = 2; + } + if (n > -1) vism->setItemChecked(vism->idAt(n), true); + mm->insertItem(tr("&Visibility on roster"), vism); + } + // Avatars #ifdef AVATARS - QPopupMenu *avpm = new QPopupMenu(&pm); + QPopupMenu *avpm = new QPopupMenu(mm); d->cv->qa_assignAvatar->addTo(avpm); d->cv->qa_clearAvatar->setEnabled(d->pa->avatarFactory()->hasManualAvatar(u->jid())); d->cv->qa_clearAvatar->addTo(avpm); - pm.insertItem(tr("&Avatar"), avpm); + mm->insertItem(tr("&Avatar"), avpm); avpm->setEnabled(option.avatarsEnabled); #endif if(d->pa->psi()->pgp()) { if(u->publicKeyID().isEmpty()) - pm.insertItem(IconsetFactory::iconPixmap("psi/gpg-yes"), tr("Assign Open&PGP key"), 21); + mm->insertItem(IconsetFactory::iconPixmap("psi/gpg-yes"), tr("Assign Open&PGP key"), 21); else - pm.insertItem(IconsetFactory::iconPixmap("psi/gpg-no"), tr("Unassign Open&PGP key"), 22); + mm->insertItem(IconsetFactory::iconPixmap("psi/gpg-no"), tr("Unassign Open&PGP key"), 22); } + + pm.insertItem(tr("More properties"), mm); + // END More properties pm.insertItem(tr("Sen&d Status"), 24); @@ -2025,6 +2122,28 @@ qa_vcard = new IconAction("", "psi/vCard", tr("User &Info"), QListView::CTRL+QListView::Key_I, this); connect(qa_vcard, SIGNAL(activated()), SLOT(doVCard())); + // More properties + qa_contactSoundMsgOn = new IconAction("", tr("On"), QKeySequence(), this); + connect(qa_contactSoundMsgOn, SIGNAL(activated()), SLOT(doContactSoundMsgOn())); + qa_contactSoundMsgOff = new IconAction("", tr("Off"), QKeySequence(), this); + connect(qa_contactSoundMsgOff, SIGNAL(activated()), SLOT(doContactSoundMsgOff())); + qa_contactSoundMsgDefault = new IconAction("", tr("Default"), QKeySequence(), this); + connect(qa_contactSoundMsgDefault, SIGNAL(activated()), SLOT(doContactSoundMsgDefault())); + + qa_contactPopupAvailOn = new IconAction("", tr("On"), QKeySequence(), this); + connect(qa_contactPopupAvailOn, SIGNAL(activated()), SLOT(doContactPopupAvailOn())); + qa_contactPopupAvailOff = new IconAction("", tr("Off"), QKeySequence(), this); + connect(qa_contactPopupAvailOff, SIGNAL(activated()), SLOT(doContactPopupAvailOff())); + qa_contactPopupAvailDefault = new IconAction("", tr("Default"), QKeySequence(), this); + connect(qa_contactPopupAvailDefault, SIGNAL(activated()), SLOT(doContactPopupAvailDefault())); + + qa_contactVisibleOn = new IconAction("", tr("On"), QKeySequence(), this); + connect(qa_contactVisibleOn, SIGNAL(activated()), SLOT(doContactVisibleOn())); + qa_contactVisibleOff = new IconAction("", tr("Off"), QKeySequence(), this); + connect(qa_contactVisibleOff, SIGNAL(activated()), SLOT(doContactVisibleOff())); + qa_contactVisibleDefault = new IconAction("", tr("Default"), QKeySequence(), this); + connect(qa_contactVisibleDefault, SIGNAL(activated()), SLOT(doContactVisibleDefault())); + if(option.lockdown.roster) { qa_ren->setEnabled(false); qa_rem->setEnabled(false); @@ -2387,6 +2506,81 @@ i->contactProfile()->scRename(i); } +// More Properties +// Message sound notification +void ContactView::doContactSoundMsgOn() +{ + ContactViewItem *i = (ContactViewItem *)selectedItem(); + option.contactSoundMsg[i->u()->jid().bare()] = 1; + //QMessageBox::information(0, "Sound on for JID", i->u()->jid().bare()); +} + +void ContactView::doContactSoundMsgOff() +{ + ContactViewItem *i = (ContactViewItem *)selectedItem(); + option.contactSoundMsg[i->u()->jid().bare()] = 0; +} + +void ContactView::doContactSoundMsgDefault() +{ + ContactViewItem *i = (ContactViewItem *)selectedItem(); + option.contactSoundMsg[i->u()->jid().bare()] = -1; +} + +// On/offline popup notification +void ContactView::doContactPopupAvailOn() +{ + ContactViewItem *i = (ContactViewItem *)selectedItem(); + option.contactPopupAvail[i->u()->jid().bare()] = 1; +} + +void ContactView::doContactPopupAvailOff() +{ + ContactViewItem *i = (ContactViewItem *)selectedItem(); + option.contactPopupAvail[i->u()->jid().bare()] = 0; +} + +void ContactView::doContactPopupAvailDefault() +{ + ContactViewItem *i = (ContactViewItem *)selectedItem(); + option.contactPopupAvail[i->u()->jid().bare()] = -1; +} + +// Visibility on roster +void ContactView::doContactVisibleOn() +{ + ContactViewItem *i = (ContactViewItem *)selectedItem(); + option.contactVisible[i->u()->jid().bare()] = 1; + + QPtrListIterator it(d->profiles); + for(ContactProfile *cp; (cp = it.current()); ++it) { + cp->addAllNeededContactItems(); + } +} + +void ContactView::doContactVisibleOff() +{ + ContactViewItem *i = (ContactViewItem *)selectedItem(); + option.contactVisible[i->u()->jid().bare()] = 0; + + QPtrListIterator it(d->profiles); + for(ContactProfile *cp; (cp = it.current()); ++it) { + cp->removeAllUnneededContactItems(); + } +} + +void ContactView::doContactVisibleDefault() +{ + ContactViewItem *i = (ContactViewItem *)selectedItem(); + option.contactVisible[i->u()->jid().bare()] = -1; + + QPtrListIterator it(d->profiles); + for(ContactProfile *cp; (cp = it.current()); ++it) { + cp->removeAllUnneededContactItems(); + cp->addAllNeededContactItems(); + } +} + void ContactView::doAssignAvatar() { // FIXME: Should check the supported filetypes dynamically diff --exclude='*orig' -Naur psi-0.10-test3-orig/src/contactview.h psi-0.10-test3/src/contactview.h --- psi-0.10-test3-orig/src/contactview.h 2005-11-23 20:30:23.000000000 +0000 +++ psi-0.10-test3/src/contactview.h 2005-11-23 20:40:30.000000000 +0000 @@ -198,6 +198,10 @@ QTimer *animTimer() const; IconAction *qa_send, *qa_chat, *qa_ren, *qa_hist, *qa_logon, *qa_recv, *qa_rem, *qa_vcard; + // More properties + IconAction *qa_contactSoundMsgOn, *qa_contactSoundMsgOff, *qa_contactSoundMsgDefault; + IconAction *qa_contactPopupAvailOn, *qa_contactPopupAvailOff, *qa_contactPopupAvailDefault; + IconAction *qa_contactVisibleOn, *qa_contactVisibleOff, *qa_contactVisibleDefault; IconAction *qa_assignAvatar, *qa_clearAvatar; QSize minimumSizeHint() const; @@ -248,6 +252,17 @@ void doLogon(); void doRemove(); + // More properties + void doContactSoundMsgOn(); + void doContactSoundMsgOff(); + void doContactSoundMsgDefault(); + void doContactPopupAvailOn(); + void doContactPopupAvailOff(); + void doContactPopupAvailDefault(); + void doContactVisibleOn(); + void doContactVisibleOff(); + void doContactVisibleDefault(); + void doAssignAvatar(); void doClearAvatar(); diff --exclude='*orig' -Naur psi-0.10-test3-orig/src/psiaccount.cpp psi-0.10-test3/src/psiaccount.cpp --- psi-0.10-test3-orig/src/psiaccount.cpp 2005-11-23 20:30:24.000000000 +0000 +++ psi-0.10-test3/src/psiaccount.cpp 2005-11-23 20:40:30.000000000 +0000 @@ -1348,11 +1348,12 @@ bool doSound = false; bool doPopup = false; + bool local = false; QPtrList list = findRelavent(j); QPtrListIterator it(list); for(UserListItem *u; (u = it.current()); ++it) { bool doAnim = false; - bool local = false; + local = false; if(u->isSelf() && res.name() == d->client->resource()) local = true; @@ -1415,9 +1416,21 @@ if(doSound) playSound(option.onevent[eOnline]); + if (option.ppOnline && notifyOnlineOk) + doPopup = true; + // custom contact availability popup notification + if (option.contactPopupAvail.contains(j.bare()) && !local && notifyOnlineOk) + { + // custom value is set + if (option.contactPopupAvail[j.bare()] == 1) + doPopup = true; + else if (option.contactPopupAvail[j.bare()] == 0) + doPopup = false; + } + #if !defined(Q_WS_MAC) || !defined(HAVE_GROWL) // Do the popup test earlier (to avoid needless JID lookups) - if ((popupType == PopupOnline && option.ppOnline) || (popupType == PopupStatusChange && option.ppStatus)) + if ((popupType == PopupOnline && doPopup) || (popupType == PopupStatusChange && option.ppStatus)) #endif if(notifyOnlineOk && doPopup && d->doPopups && !d->blockTransportPopupList->find(j, popupType == PopupOnline) && makeSTATUS(status()) != STATUS_DND ) { QString name; @@ -1452,6 +1465,7 @@ bool doSound = false; bool doPopup = false; + bool local = false; if ( j.user().isEmpty() ) new BlockTransportPopup(d->blockTransportPopupList, j); @@ -1459,7 +1473,7 @@ QPtrList list = findRelavent(j); QPtrListIterator it(list); for(UserListItem *u; (u = it.current()); ++it) { - bool local = false; + local = false; if(u->isSelf() && res.name() == d->client->resource()) local = true; @@ -1488,6 +1502,16 @@ if(doSound) playSound(option.onevent[eOffline]); + // custom contact availability popup notification + if (option.contactPopupAvail.contains(j.bare()) && !local && !isDisconnecting) + { + // custom value is set + if (option.contactPopupAvail[j.bare()] == 1) + doPopup = true; + else if (option.contactPopupAvail[j.bare()] == 0) + doPopup = false; + } + #if !defined(Q_WS_MAC) || !defined(HAVE_GROWL) // Do the popup test earlier (to avoid needless JID lookups) if (option.ppOffline) @@ -1888,7 +1912,7 @@ d->lastStatus = lastStatus; } -void PsiAccount::playSound(const QString &str) +void PsiAccount::playSound(const QString &str, bool force) { if(str.isEmpty()) return; @@ -1932,10 +1956,10 @@ s = makeSTATUS(status()); // no away sounds? - if(option.noAwaySound && (s == STATUS_AWAY || s == STATUS_XA || s == STATUS_DND)) + if(!force && option.noAwaySound && (s == STATUS_AWAY || s == STATUS_XA || s == STATUS_DND)) return; - d->psi->playSound(str); + d->psi->playSound(str, force); } } @@ -3171,7 +3195,16 @@ //or in a window if( c && ( d->psi->isChatTabbed(c) || !c->isHidden() ) ) { c->incomingMessage(m); - playSound(option.onevent[eChat2]); + if (option.contactSoundMsg.contains(e->from().bare()) && + option.contactSoundMsg[e->from().bare()] != -1) + { + if (option.contactSoundMsg[e->from().bare()] == 1) + playSound(option.onevent[eChat2], true); + } + else + { + playSound(option.onevent[eChat2]); + } if(option.alertOpenChats && !d->psi->isChatActiveWindow(c)) { // to alert the chat also, we put it in the queue me->setSentToChatWindow(true); @@ -3181,23 +3214,60 @@ } else { bool firstChat = !d->eventQueue->hasChats(e->from()); - playSound(option.onevent[firstChat ? eChat1: eChat2]); + if (option.contactSoundMsg.contains(e->from().bare()) && + option.contactSoundMsg[e->from().bare()] != -1) + { + if (option.contactSoundMsg[e->from().bare()] == 1) + playSound(option.onevent[firstChat ? eChat1: eChat2], true); + } + else + { + playSound(option.onevent[firstChat ? eChat1: eChat2]); + } } } // /chat else if (m.type() == "headline") { - playSound(option.onevent[eHeadline]); + if (option.contactSoundMsg.contains(e->from().bare()) && + option.contactSoundMsg[e->from().bare()] != -1) + { + if (option.contactSoundMsg[e->from().bare()] == 1) + playSound(option.onevent[eHeadline], true); + } + else + { + playSound(option.onevent[eHeadline]); + } doPopup = true; popupType = PsiPopup::AlertHeadline; } // /headline else if (m.type() == "") { - playSound(option.onevent[eMessage]); + if (option.contactSoundMsg.contains(e->from().bare()) && + option.contactSoundMsg[e->from().bare()] != -1) + { + if (option.contactSoundMsg[e->from().bare()] == 1) + playSound(option.onevent[eMessage], true); + } + else + { + playSound(option.onevent[eMessage]); + } if (m.type() == "") { doPopup = true; popupType = PsiPopup::AlertMessage; } } // /"" - else - playSound(option.onevent[eSystem]); + else { + if (option.contactSoundMsg.contains(e->from().bare()) && + option.contactSoundMsg[e->from().bare()] != -1) + { + if (option.contactSoundMsg[e->from().bare()] == 1) + playSound(option.onevent[eSystem], true); + } + else + { + playSound(option.onevent[eSystem]); + } + } if(m.type() == "error") { // FIXME: handle message errors diff --exclude='*orig' -Naur psi-0.10-test3-orig/src/psiaccount.h psi-0.10-test3/src/psiaccount.h --- psi-0.10-test3-orig/src/psiaccount.h 2005-11-23 20:30:21.000000000 +0000 +++ psi-0.10-test3/src/psiaccount.h 2005-11-23 20:40:30.000000000 +0000 @@ -189,7 +189,7 @@ UserList *userList() const; bool checkConnected(QWidget *parent=0); - void playSound(const QString &); + void playSound(const QString &, bool force = false); QLabel *accountLabel(QWidget *parent=0, bool simpleMode=false); QStringList hiddenChats(const Jid &) const; diff --exclude='*orig' -Naur psi-0.10-test3-orig/src/psicon.cpp psi-0.10-test3/src/psicon.cpp --- psi-0.10-test3-orig/src/psicon.cpp 2005-11-23 20:30:24.000000000 +0000 +++ psi-0.10-test3/src/psicon.cpp 2005-11-23 20:40:30.000000000 +0000 @@ -1256,9 +1256,9 @@ pa->openNextEvent(); } -void PsiCon::playSound(const QString &str) +void PsiCon::playSound(const QString &str, bool force) { - if(str.isEmpty() || !useSound) + if(str.isEmpty() || !useSound && !force) return; soundPlay(str); diff --exclude='*orig' -Naur psi-0.10-test3-orig/src/psicon.h psi-0.10-test3/src/psicon.h --- psi-0.10-test3-orig/src/psicon.h 2005-11-23 20:30:22.000000000 +0000 +++ psi-0.10-test3/src/psicon.h 2005-11-23 20:40:30.000000000 +0000 @@ -118,7 +118,7 @@ void removeAccount(PsiAccount *); void enableAccount(PsiAccount *, bool e=TRUE); - void playSound(const QString &); + void playSound(const QString &, bool force = false); void raiseMainwin(); // global event handling diff --exclude='*orig' -Naur psi-0.10-test3-orig/src/psi_profiles.cpp psi-0.10-test3/src/psi_profiles.cpp --- psi-0.10-test3-orig/src/psi_profiles.cpp 2005-11-23 20:30:24.000000000 +0000 +++ psi-0.10-test3/src/psi_profiles.cpp 2005-11-23 20:40:30.000000000 +0000 @@ -949,6 +949,63 @@ p_priority.appendChild(textTag(doc, "auth", prefs.eventPriorityAuth)); p_priority.appendChild(textTag(doc, "file", prefs.eventPriorityFile)); } + + // More contact properties: custom message sound notification + { + QDomElement p_csound = doc.createElement("contactSoundMsg"); + p_events.appendChild(p_csound); + + QString jid; + QMapIterator it = prefs.contactSoundMsg.begin(); + for ( ; it != prefs.contactSoundMsg.end(); ++it) { + if (it.data() != -1) // don't save "default" setting + { + QDomElement contact = doc.createElement("contact"); + p_csound.appendChild(contact); + + contact.setAttribute("jid", it.key()); + contact.setAttribute("sound", it.data()); + } + } + } + + // More contact properties: custom availability popup notification + { + QDomElement p_cpopup = doc.createElement("contactPopupAvail"); + p_events.appendChild(p_cpopup); + + QString jid; + QMapIterator it = prefs.contactPopupAvail.begin(); + for ( ; it != prefs.contactPopupAvail.end(); ++it) { + if (it.data() != -1) // don't save "default" setting + { + QDomElement contact = doc.createElement("contact"); + p_cpopup.appendChild(contact); + + contact.setAttribute("jid", it.key()); + contact.setAttribute("popup", it.data()); + } + } + } + + // More contact properties: custom visibility on roster + { + QDomElement p_cvis = doc.createElement("contactVisible"); + p_events.appendChild(p_cvis); + + QString jid; + QMapIterator it = prefs.contactVisible.begin(); + for ( ; it != prefs.contactVisible.end(); ++it) { + if (it.data() != -1) // don't save "default" setting + { + QDomElement contact = doc.createElement("contact"); + p_cvis.appendChild(contact); + + contact.setAttribute("jid", it.key()); + contact.setAttribute("visible", it.data()); + } + } + } } { @@ -1718,6 +1775,45 @@ readNumEntry(tag, "auth", &prefs.eventPriorityAuth); readNumEntry(tag, "file", &prefs.eventPriorityFile); } + + // More contact properties: custom message sound notifications + QDomElement sounds = findSubTag(p_events, "contactSoundMsg", &found); + if (found) { + prefs.contactSoundMsg.clear(); + for (QDomNode n = sounds.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement el = n.toElement(); + if ( el.isNull() || el.nodeName() != "contact") + continue; + + prefs.contactSoundMsg[el.attribute("jid")] = el.attribute("sound").toInt(); + } + } + + // More contact properties: custom availability popup notifications + QDomElement popups = findSubTag(p_events, "contactPopupAvail", &found); + if (found) { + prefs.contactPopupAvail.clear(); + for (QDomNode n = popups.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement el = n.toElement(); + if ( el.isNull() || el.nodeName() != "contact") + continue; + + prefs.contactPopupAvail[el.attribute("jid")] = el.attribute("popup").toInt(); + } + } + + // More contact properties: custom visibility on roster + QDomElement cvis = findSubTag(p_events, "contactVisible", &found); + if (found) { + prefs.contactVisible.clear(); + for (QDomNode n = cvis.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement el = n.toElement(); + if ( el.isNull() || el.nodeName() != "contact") + continue; + + prefs.contactVisible[el.attribute("jid")] = el.attribute("visible").toInt(); + } + } } QDomElement p_pres = findSubTag(p, "presence", &found);