File indexing completed on 2024-12-08 13:17:34

0001 /*
0002     This file is part of Akonadi.
0003     SPDX-FileCopyrightText: 2003 Andreas Gungl <a.gungl@gmx.de>
0004     SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
0005     SPDX-FileCopyrightText: 2010 Leo Franchi <lfranchi@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #include "messagestatus.h"
0011 
0012 #include <Akonadi/MessageFlags>
0013 
0014 #include <QString>
0015 
0016 using namespace Akonadi;
0017 
0018 /** The message status format. These can be or'd together.
0019     Note, that the StatusIgnored implies the
0020     status to be Read.
0021     This is done in isRead() and related getters.
0022     So we can preserve the state when switching a
0023     thread to Ignored and back. */
0024 enum Status {
0025     StatusUnknown = 0x00000000,
0026     StatusUnread = 0x00000002, // deprecated
0027     StatusRead = 0x00000004,
0028     StatusDeleted = 0x00000010,
0029     StatusReplied = 0x00000020,
0030     StatusForwarded = 0x00000040,
0031     StatusQueued = 0x00000080,
0032     StatusSent = 0x00000100,
0033     StatusFlag = 0x00000200, // flag means important
0034     StatusWatched = 0x00000400,
0035     StatusIgnored = 0x00000800, // forces isRead()
0036     StatusToAct = 0x00001000,
0037     StatusSpam = 0x00002000,
0038     StatusHam = 0x00004000,
0039     StatusHasAttachment = 0x00008000,
0040     StatusHasInvitation = 0x00010000,
0041     StatusSigned = 0x00020000,
0042     StatusEncrypted = 0x00040000,
0043     StatusHasError = 0x00080000
0044 };
0045 
0046 MessageStatus::MessageStatus()
0047 {
0048     mStatus = StatusUnknown;
0049 }
0050 
0051 bool MessageStatus::operator==(MessageStatus other) const
0052 {
0053     return mStatus == other.mStatus;
0054 }
0055 
0056 bool MessageStatus::operator!=(MessageStatus other) const
0057 {
0058     return mStatus != other.mStatus;
0059 }
0060 
0061 bool MessageStatus::operator&(MessageStatus other) const
0062 {
0063     if (mStatus == StatusUnread) {
0064         return !(other.mStatus & StatusRead);
0065     }
0066 
0067     if (other.mStatus == StatusUnread) {
0068         return !(mStatus & StatusRead);
0069     }
0070 
0071     return mStatus & other.mStatus;
0072 }
0073 
0074 void MessageStatus::clear()
0075 {
0076     mStatus = StatusUnknown;
0077 }
0078 
0079 void MessageStatus::set(MessageStatus other)
0080 {
0081     Q_ASSERT(!(other.mStatus & StatusUnread));
0082 
0083     // Those static are exclusive, but we have to lock at the
0084     // internal representation because Ignored can manipulate
0085     // the result of the getter methods.
0086     if (other.mStatus & StatusRead) {
0087         setRead();
0088     }
0089     if (other.isDeleted()) {
0090         setDeleted();
0091     }
0092     if (other.isReplied()) {
0093         setReplied();
0094     }
0095     if (other.isForwarded()) {
0096         setForwarded();
0097     }
0098     if (other.isQueued()) {
0099         setQueued();
0100     }
0101     if (other.isSent()) {
0102         setSent();
0103     }
0104     if (other.isImportant()) {
0105         setImportant();
0106     }
0107 
0108     if (other.isWatched()) {
0109         setWatched();
0110     }
0111     if (other.isIgnored()) {
0112         setIgnored();
0113     }
0114     if (other.isToAct()) {
0115         setToAct();
0116     }
0117     if (other.isSpam()) {
0118         setSpam();
0119     }
0120     if (other.isHam()) {
0121         setHam();
0122     }
0123     if (other.hasAttachment()) {
0124         setHasAttachment();
0125     }
0126     if (other.hasInvitation()) {
0127         setHasInvitation();
0128     }
0129     if (other.isSigned()) {
0130         setSigned();
0131     }
0132     if (other.isEncrypted()) {
0133         setEncrypted();
0134     }
0135     if (other.hasError()) {
0136         setHasError();
0137     }
0138 }
0139 
0140 void MessageStatus::toggle(MessageStatus other)
0141 {
0142     Q_ASSERT(!(other.mStatus & StatusUnread));
0143 
0144     if (other.isDeleted()) {
0145         setDeleted(!(mStatus & StatusDeleted));
0146     }
0147     if (other.isReplied()) {
0148         setReplied(!(mStatus & StatusReplied));
0149     }
0150     if (other.isForwarded()) {
0151         setForwarded(!(mStatus & StatusForwarded));
0152     }
0153     if (other.isQueued()) {
0154         setQueued(!(mStatus & StatusQueued));
0155     }
0156     if (other.isSent()) {
0157         setSent(!(mStatus & StatusSent));
0158     }
0159     if (other.isImportant()) {
0160         setImportant(!(mStatus & StatusFlag));
0161     }
0162 
0163     if (other.isWatched()) {
0164         setWatched(!(mStatus & StatusWatched));
0165     }
0166     if (other.isIgnored()) {
0167         setIgnored(!(mStatus & StatusIgnored));
0168     }
0169     if (other.isToAct()) {
0170         setToAct(!(mStatus & StatusToAct));
0171     }
0172     if (other.isSpam()) {
0173         setSpam(!(mStatus & StatusSpam));
0174     }
0175     if (other.isHam()) {
0176         setHam(!(mStatus & StatusHam));
0177     }
0178     if (other.hasAttachment()) {
0179         setHasAttachment(!(mStatus & StatusHasAttachment));
0180     }
0181     if (other.hasInvitation()) {
0182         setHasInvitation(!(mStatus & StatusHasInvitation));
0183     }
0184     if (other.isSigned()) {
0185         setSigned(!(mStatus & StatusSigned));
0186     }
0187     if (other.isEncrypted()) {
0188         setEncrypted(!(mStatus & StatusEncrypted));
0189     }
0190     if (other.hasError()) {
0191         setHasError(!(mStatus & StatusHasError));
0192     }
0193 }
0194 
0195 bool MessageStatus::isOfUnknownStatus() const
0196 {
0197     return mStatus == StatusUnknown;
0198 }
0199 
0200 bool MessageStatus::isRead() const
0201 {
0202     return (mStatus & StatusRead) || (mStatus & StatusIgnored);
0203 }
0204 
0205 bool MessageStatus::isDeleted() const
0206 {
0207     return mStatus & StatusDeleted;
0208 }
0209 
0210 bool MessageStatus::isReplied() const
0211 {
0212     return mStatus & StatusReplied;
0213 }
0214 
0215 bool MessageStatus::isForwarded() const
0216 {
0217     return mStatus & StatusForwarded;
0218 }
0219 
0220 bool MessageStatus::isQueued() const
0221 {
0222     return mStatus & StatusQueued;
0223 }
0224 
0225 bool MessageStatus::isSent() const
0226 {
0227     return mStatus & StatusSent;
0228 }
0229 
0230 bool MessageStatus::isImportant() const
0231 {
0232     return mStatus & StatusFlag;
0233 }
0234 
0235 bool MessageStatus::isWatched() const
0236 {
0237     return mStatus & StatusWatched;
0238 }
0239 
0240 bool MessageStatus::isIgnored() const
0241 {
0242     return mStatus & StatusIgnored;
0243 }
0244 
0245 bool MessageStatus::isToAct() const
0246 {
0247     return mStatus & StatusToAct;
0248 }
0249 
0250 bool MessageStatus::isSpam() const
0251 {
0252     return mStatus & StatusSpam;
0253 }
0254 
0255 bool MessageStatus::isHam() const
0256 {
0257     return mStatus & StatusHam;
0258 }
0259 
0260 bool MessageStatus::hasAttachment() const
0261 {
0262     return mStatus & StatusHasAttachment;
0263 }
0264 
0265 bool MessageStatus::hasInvitation() const
0266 {
0267     return mStatus & StatusHasInvitation;
0268 }
0269 
0270 bool MessageStatus::isSigned() const
0271 {
0272     return mStatus & StatusSigned;
0273 }
0274 
0275 bool MessageStatus::isEncrypted() const
0276 {
0277     return mStatus & StatusEncrypted;
0278 }
0279 
0280 bool MessageStatus::hasError() const
0281 {
0282     return mStatus & StatusHasError;
0283 }
0284 
0285 void MessageStatus::setRead(bool read)
0286 {
0287     if (read) {
0288         mStatus |= StatusRead;
0289     } else {
0290         mStatus &= ~StatusRead;
0291     }
0292 }
0293 
0294 void MessageStatus::setDeleted(bool deleted)
0295 {
0296     if (deleted) {
0297         mStatus |= StatusDeleted;
0298     } else {
0299         mStatus &= ~StatusDeleted;
0300     }
0301 }
0302 
0303 void MessageStatus::setReplied(bool replied)
0304 {
0305     if (replied) {
0306         mStatus |= StatusReplied;
0307     } else {
0308         mStatus &= ~StatusReplied;
0309     }
0310 }
0311 
0312 void MessageStatus::setForwarded(bool forwarded)
0313 {
0314     if (forwarded) {
0315         mStatus |= StatusForwarded;
0316     } else {
0317         mStatus &= ~StatusForwarded;
0318     }
0319 }
0320 
0321 void MessageStatus::setQueued(bool queued)
0322 {
0323     if (queued) {
0324         mStatus |= StatusQueued;
0325     } else {
0326         mStatus &= ~StatusQueued;
0327     }
0328 }
0329 
0330 void MessageStatus::setSent(bool sent)
0331 {
0332     if (sent) {
0333         mStatus &= ~StatusQueued;
0334         mStatus |= StatusSent;
0335     } else {
0336         mStatus &= ~StatusSent;
0337     }
0338 }
0339 
0340 void MessageStatus::setImportant(bool important)
0341 {
0342     if (important) {
0343         mStatus |= StatusFlag;
0344     } else {
0345         mStatus &= ~StatusFlag;
0346     }
0347 }
0348 
0349 // Watched and ignored are mutually exclusive
0350 void MessageStatus::setWatched(bool watched)
0351 {
0352     if (watched) {
0353         mStatus &= ~StatusIgnored;
0354         mStatus |= StatusWatched;
0355     } else {
0356         mStatus &= ~StatusWatched;
0357     }
0358 }
0359 
0360 void MessageStatus::setIgnored(bool ignored)
0361 {
0362     if (ignored) {
0363         mStatus &= ~StatusWatched;
0364         mStatus |= StatusIgnored;
0365     } else {
0366         mStatus &= ~StatusIgnored;
0367     }
0368 }
0369 
0370 void MessageStatus::setToAct(bool toAct)
0371 {
0372     if (toAct) {
0373         mStatus |= StatusToAct;
0374     } else {
0375         mStatus &= ~StatusToAct;
0376     }
0377 }
0378 
0379 // Ham and Spam are mutually exclusive
0380 void MessageStatus::setSpam(bool spam)
0381 {
0382     if (spam) {
0383         mStatus &= ~StatusHam;
0384         mStatus |= StatusSpam;
0385     } else {
0386         mStatus &= ~StatusSpam;
0387     }
0388 }
0389 
0390 void MessageStatus::setHam(bool ham)
0391 {
0392     if (ham) {
0393         mStatus &= ~StatusSpam;
0394         mStatus |= StatusHam;
0395     } else {
0396         mStatus &= ~StatusHam;
0397     }
0398 }
0399 
0400 void MessageStatus::setHasAttachment(bool withAttachment)
0401 {
0402     if (withAttachment) {
0403         mStatus |= StatusHasAttachment;
0404     } else {
0405         mStatus &= ~StatusHasAttachment;
0406     }
0407 }
0408 
0409 void MessageStatus::setHasInvitation(bool withInvitation)
0410 {
0411     if (withInvitation) {
0412         mStatus |= StatusHasInvitation;
0413     } else {
0414         mStatus &= ~StatusHasInvitation;
0415     }
0416 }
0417 
0418 void MessageStatus::setSigned(bool value)
0419 {
0420     if (value) {
0421         mStatus |= StatusSigned;
0422     } else {
0423         mStatus &= ~StatusSigned;
0424     }
0425 }
0426 
0427 void MessageStatus::setEncrypted(bool value)
0428 {
0429     if (value) {
0430         mStatus |= StatusEncrypted;
0431     } else {
0432         mStatus &= ~StatusEncrypted;
0433     }
0434 }
0435 
0436 void MessageStatus::setHasError(bool hasError)
0437 {
0438     if (hasError) {
0439         mStatus |= StatusHasError;
0440     } else {
0441         mStatus &= ~StatusHasError;
0442     }
0443 }
0444 
0445 qint32 MessageStatus::toQInt32() const
0446 {
0447     return mStatus;
0448 }
0449 
0450 void MessageStatus::fromQInt32(qint32 status)
0451 {
0452     mStatus = status;
0453 }
0454 
0455 QString MessageStatus::statusStr() const
0456 {
0457     QByteArray sstr;
0458     if (mStatus & StatusRead) {
0459         sstr += 'R';
0460     } else {
0461         sstr += 'U';
0462     }
0463     if (mStatus & StatusDeleted) {
0464         sstr += 'D';
0465     }
0466     if (mStatus & StatusReplied) {
0467         sstr += 'A';
0468     }
0469     if (mStatus & StatusForwarded) {
0470         sstr += 'F';
0471     }
0472     if (mStatus & StatusQueued) {
0473         sstr += 'Q';
0474     }
0475     if (mStatus & StatusToAct) {
0476         sstr += 'K';
0477     }
0478     if (mStatus & StatusSent) {
0479         sstr += 'S';
0480     }
0481     if (mStatus & StatusFlag) {
0482         sstr += 'G';
0483     }
0484     if (mStatus & StatusWatched) {
0485         sstr += 'W';
0486     }
0487     if (mStatus & StatusIgnored) {
0488         sstr += 'I';
0489     }
0490     if (mStatus & StatusSpam) {
0491         sstr += 'P';
0492     }
0493     if (mStatus & StatusHam) {
0494         sstr += 'H';
0495     }
0496     if (mStatus & StatusHasAttachment) {
0497         sstr += 'T';
0498     }
0499 
0500     return QLatin1String(sstr);
0501 }
0502 
0503 void MessageStatus::setStatusFromStr(const QString &aStr)
0504 {
0505     mStatus = StatusUnknown;
0506 
0507     if (aStr.contains(QLatin1Char('U'))) {
0508         setRead(false);
0509     }
0510     if (aStr.contains(QLatin1Char('R'))) {
0511         setRead();
0512     }
0513     if (aStr.contains(QLatin1Char('D'))) {
0514         setDeleted();
0515     }
0516     if (aStr.contains(QLatin1Char('A'))) {
0517         setReplied();
0518     }
0519     if (aStr.contains(QLatin1Char('F'))) {
0520         setForwarded();
0521     }
0522     if (aStr.contains(QLatin1Char('Q'))) {
0523         setQueued();
0524     }
0525     if (aStr.contains(QLatin1Char('K'))) {
0526         setToAct();
0527     }
0528     if (aStr.contains(QLatin1Char('S'))) {
0529         setSent();
0530     }
0531     if (aStr.contains(QLatin1Char('G'))) {
0532         setImportant();
0533     }
0534     if (aStr.contains(QLatin1Char('W'))) {
0535         setWatched();
0536     }
0537     if (aStr.contains(QLatin1Char('I'))) {
0538         setIgnored();
0539     }
0540     if (aStr.contains(QLatin1Char('P'))) {
0541         setSpam();
0542     }
0543     if (aStr.contains(QLatin1Char('H'))) {
0544         setHam();
0545     }
0546     if (aStr.contains(QLatin1Char('T'))) {
0547         setHasAttachment();
0548     }
0549     if (aStr.contains(QLatin1Char('C'))) {
0550         setHasAttachment(false);
0551     }
0552 }
0553 
0554 QSet<QByteArray> MessageStatus::statusFlags() const
0555 {
0556     QSet<QByteArray> flags;
0557 
0558     if (mStatus & StatusDeleted) {
0559         flags += MessageFlags::Deleted;
0560     } else {
0561         if (mStatus & StatusRead) {
0562             flags += MessageFlags::Seen;
0563         }
0564         if (mStatus & StatusReplied) {
0565             flags += MessageFlags::Answered;
0566         }
0567         if (mStatus & StatusFlag) {
0568             flags += MessageFlags::Flagged;
0569         }
0570 
0571         // non standard flags
0572         if (mStatus & StatusSent) {
0573             flags += MessageFlags::Sent;
0574         }
0575         if (mStatus & StatusQueued) {
0576             flags += MessageFlags::Queued;
0577         }
0578         if (mStatus & StatusReplied) {
0579             flags += MessageFlags::Replied;
0580         }
0581         if (mStatus & StatusForwarded) {
0582             flags += MessageFlags::Forwarded;
0583         }
0584         if (mStatus & StatusToAct) {
0585             flags += MessageFlags::ToAct;
0586         }
0587         if (mStatus & StatusWatched) {
0588             flags += MessageFlags::Watched;
0589         }
0590         if (mStatus & StatusIgnored) {
0591             flags += MessageFlags::Ignored;
0592         }
0593         if (mStatus & StatusHasAttachment) {
0594             flags += MessageFlags::HasAttachment;
0595         }
0596         if (mStatus & StatusHasInvitation) {
0597             flags += MessageFlags::HasInvitation;
0598         }
0599         if (mStatus & StatusSigned) {
0600             flags += MessageFlags::Signed;
0601         }
0602         if (mStatus & StatusEncrypted) {
0603             flags += MessageFlags::Encrypted;
0604         }
0605         if (mStatus & StatusSpam) {
0606             flags += MessageFlags::Spam;
0607         }
0608         if (mStatus & StatusHam) {
0609             flags += MessageFlags::Ham;
0610         }
0611         if (mStatus & StatusHasError) {
0612             flags += MessageFlags::HasError;
0613         }
0614     }
0615 
0616     return flags;
0617 }
0618 
0619 void MessageStatus::setStatusFromFlags(const QSet<QByteArray> &flags)
0620 {
0621     mStatus = StatusUnknown;
0622 
0623     for (const QByteArray &flag : flags) {
0624         const QByteArray &upperedFlag = flag.toUpper();
0625         if (upperedFlag == MessageFlags::Deleted) {
0626             setDeleted();
0627         } else if (upperedFlag == MessageFlags::Seen) {
0628             setRead();
0629         } else if (upperedFlag == MessageFlags::Answered) {
0630             setReplied();
0631         } else if (upperedFlag == MessageFlags::Flagged) {
0632             setImportant();
0633 
0634             // non standard flags
0635         } else if (upperedFlag == MessageFlags::Sent) {
0636             setSent();
0637         } else if (upperedFlag == MessageFlags::Queued) {
0638             setQueued();
0639         } else if (upperedFlag == MessageFlags::Replied) {
0640             setReplied();
0641         } else if (upperedFlag == MessageFlags::Forwarded) {
0642             setForwarded();
0643         } else if (upperedFlag == MessageFlags::ToAct) {
0644             setToAct();
0645         } else if (upperedFlag == MessageFlags::Watched) {
0646             setWatched();
0647         } else if (upperedFlag == MessageFlags::Ignored) {
0648             setIgnored();
0649         } else if (upperedFlag == MessageFlags::HasAttachment) {
0650             setHasAttachment();
0651         } else if (upperedFlag == MessageFlags::HasInvitation) {
0652             setHasInvitation();
0653         } else if (upperedFlag == MessageFlags::Signed) {
0654             setSigned();
0655         } else if (upperedFlag == MessageFlags::Encrypted) {
0656             setEncrypted();
0657         } else if (upperedFlag == MessageFlags::Spam) {
0658             setSpam();
0659         } else if (upperedFlag == MessageFlags::Ham) {
0660             setHam();
0661         } else if (upperedFlag == MessageFlags::HasError) {
0662             setHasError();
0663         }
0664     }
0665 }
0666 
0667 const MessageStatus MessageStatus::statusUnread()
0668 {
0669     MessageStatus st;
0670     st.mStatus = StatusUnread;
0671     return st;
0672 }
0673 
0674 const MessageStatus MessageStatus::statusRead()
0675 {
0676     MessageStatus st;
0677     st.setRead();
0678     return st;
0679 }
0680 
0681 const MessageStatus MessageStatus::statusDeleted()
0682 {
0683     MessageStatus st;
0684     st.setDeleted();
0685     return st;
0686 }
0687 
0688 const MessageStatus MessageStatus::statusReplied()
0689 {
0690     MessageStatus st;
0691     st.setReplied();
0692     return st;
0693 }
0694 
0695 const MessageStatus MessageStatus::statusForwarded()
0696 {
0697     MessageStatus st;
0698     st.setForwarded();
0699     return st;
0700 }
0701 
0702 const MessageStatus MessageStatus::statusQueued()
0703 {
0704     MessageStatus st;
0705     st.setQueued();
0706     return st;
0707 }
0708 
0709 const MessageStatus MessageStatus::statusSent()
0710 {
0711     MessageStatus st;
0712     st.setSent();
0713     return st;
0714 }
0715 
0716 const MessageStatus MessageStatus::statusImportant()
0717 {
0718     MessageStatus st;
0719     st.setImportant();
0720     return st;
0721 }
0722 
0723 const MessageStatus MessageStatus::statusWatched()
0724 {
0725     MessageStatus st;
0726     st.setWatched();
0727     return st;
0728 }
0729 
0730 const MessageStatus MessageStatus::statusIgnored()
0731 {
0732     MessageStatus st;
0733     st.setIgnored();
0734     return st;
0735 }
0736 
0737 const MessageStatus MessageStatus::statusToAct()
0738 {
0739     MessageStatus st;
0740     st.setToAct();
0741     return st;
0742 }
0743 
0744 const MessageStatus MessageStatus::statusSpam()
0745 {
0746     MessageStatus st;
0747     st.setSpam();
0748     return st;
0749 }
0750 
0751 const MessageStatus MessageStatus::statusHam()
0752 {
0753     MessageStatus st;
0754     st.setHam();
0755     return st;
0756 }
0757 
0758 const MessageStatus MessageStatus::statusHasAttachment()
0759 {
0760     MessageStatus st;
0761     st.setHasAttachment();
0762     return st;
0763 }
0764 
0765 const MessageStatus MessageStatus::statusHasInvitation()
0766 {
0767     MessageStatus st;
0768     st.setHasInvitation();
0769     return st;
0770 }
0771 
0772 const MessageStatus MessageStatus::statusSigned()
0773 {
0774     MessageStatus st;
0775     st.setSigned();
0776     return st;
0777 }
0778 
0779 const MessageStatus MessageStatus::statusEncrypted()
0780 {
0781     MessageStatus st;
0782     st.setEncrypted();
0783     return st;
0784 }
0785 
0786 const MessageStatus MessageStatus::statusHasError()
0787 {
0788     MessageStatus st;
0789     st.setHasError();
0790     return st;
0791 }
0792 
0793 QDebug operator<<(QDebug d, const MessageStatus &t)
0794 {
0795     d << "status " << t.statusStr();
0796     return d;
0797 }