diff -Nru birdtray-1.4/debian/changelog birdtray-1.5/debian/changelog --- birdtray-1.4/debian/changelog 2019-01-10 08:47:09.000000000 +0000 +++ birdtray-1.5/debian/changelog 2019-02-16 22:16:33.000000000 +0000 @@ -1,3 +1,9 @@ +birdtray (1.5-1) unstable; urgency=medium + + * New upstream release. + + -- Adam Borowski Sat, 16 Feb 2019 23:16:33 +0100 + birdtray (1.4-3) unstable; urgency=medium * Add epoch to the versioned build-dependency. diff -Nru birdtray-1.4/debian/control birdtray-1.5/debian/control --- birdtray-1.4/debian/control 2019-01-10 08:46:22.000000000 +0000 +++ birdtray-1.5/debian/control 2019-02-16 21:46:55.000000000 +0000 @@ -27,5 +27,5 @@ insides, it suffers from problems like noticing new mails only after a delay, having to restart Thunderbird just to hide its window, etc -- you'd want to use an extension like firetray instead -- but, it is - likely that support for Thunderbird extensions will be dropped soon, + likely that support for Thunderbird XUL extensions will be dropped soon, possibly by the time you read these words. diff -Nru birdtray-1.4/README.md birdtray-1.5/README.md --- birdtray-1.4/README.md 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/README.md 2019-02-16 07:43:08.000000000 +0000 @@ -27,13 +27,16 @@ - Has configurable "New Email" functionality, allowing pre-configured email templates. -## Compiling +## Building -Currently the only way to test Birdtray is to build it from source, which should be easy on Linux, but may be cumbersome on other OSes. You would need the following libraries: +To build Birdtray from source, you would need the following libraries: - Qt 5.5 or higher with "x11extras-dev" or "x11extras-devel" module installed (it is usually NOT installed by default); - sqlite3 (i.e. libsqlite3-dev or libsqlite3-devel) -- On Debian you need to install the following packages: qt5-defaults libsqlite3-dev libqt5x11extras-dev + +On Debian you need to install the following packages: ``qt5-defaults libsqlite3-dev libqt5x11extras-dev`` + +On OpenSuSE you need to install ``libqt5-qtbase-devel libqt5-qtx11extras-devel sqlite3-devel`` To build, please do the following: @@ -44,18 +47,17 @@ Launch the ./birdtray executable from the local directory. It will show Thunderbird icon in system tray. -Right-click on this icon, and click Settings. Select the Thunderbird profile folder - must contain the file "global-messages-db.sqlite". -Then select the font and default color (which will be used if more than one monitored folder has new mail). +Right-click on this icon, and click Settings. Go to Monitoring tab ans select the Thunderbird MSF file for the mailbox you'd like to monitor. You can specify different notification colors for each mailbox. Birdtray will show the new email count using this color if only this folder has new mail. If more than one folder has new mail, the default color will be used. -Then click on Accounts tab, and add one or more folders. You can specify different notification colors for each folder. Birdtray will show the new email count using this color if only this folder has new mail. If more than one folder has new mail, the default color will be used. +Then select the font and default color (which will be used if more than one monitored folder has new mail). You can also enable birdtray to start Thunderbird when you start Birdtray, or enable show/hide Thunderbird when the system tray icon is clicked, in settings. -Once you change settings, you must restart birdtray for the new settings to take effect. +Once you change settings, often you need to restart birdtray for the new settings to take effect. -Because Thunderbird updates database after 5-10 seconds when the emails are read or new emails arrived, there is a delay between a new email is arrived and birdtray "sees" it. This is a known issue which currently I do not know how to address. +## Troubleshooting -If you have no unread email, but Birdtray still shows there is unread email, this is caused by Thunderbird not properly updating the messages database. Use the "Fix" button in Settings dialog to fix that. +If you have lots of unread messages shown, and you are using global search database to look for unread messages, it may be because the database is corrupt or too old. You may delete the file global-messages-db.sqlite and restart Thunderbird which would rebuild this file. This will also help if "search" function in Thunderbird finds emails which no longer exist. ## Submitting bugs and feature requests diff -Nru birdtray-1.4/src/birdtray.pro birdtray-1.5/src/birdtray.pro --- birdtray-1.4/src/birdtray.pro 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/birdtray.pro 2019-02-16 07:43:08.000000000 +0000 @@ -42,7 +42,8 @@ setting_newemail.cpp \ modelnewemails.cpp \ modelaccounttree.cpp \ - morkparser.cpp + morkparser.cpp \ + utils.cpp HEADERS += \ trayicon.h \ @@ -61,7 +62,8 @@ setting_newemail.h \ modelnewemails.h \ modelaccounttree.h \ - morkparser.h + morkparser.h \ + utils.h FORMS += \ dialogaddeditaccount.ui \ diff -Nru birdtray-1.4/src/dialogsettings.cpp birdtray-1.5/src/dialogsettings.cpp --- birdtray-1.4/src/dialogsettings.cpp 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/dialogsettings.cpp 2019-02-16 07:43:08.000000000 +0000 @@ -36,6 +36,7 @@ connect( btnAccountAdd, &QPushButton::clicked, this, &DialogSettings::accountAdd ); connect( btnAccountEdit, &QPushButton::clicked, this, &DialogSettings::accountEdit ); connect( btnAccountRemove, &QPushButton::clicked, this, &DialogSettings::accountRemove ); + connect( btnAccountAddMultiple, &QPushButton::clicked, this, &DialogSettings::accountAddMultiple ); connect( treeNewEmails, &QTreeView::doubleClicked, this, &DialogSettings::newEmailEditIndex ); connect( btnNewEmailAdd, &QPushButton::clicked, this, &DialogSettings::newEmailAdd ); @@ -62,6 +63,9 @@ boxEnableNewEmail->setChecked( pSettings->mNewEmailMenuEnabled ); boxBlinkingUsesAlpha->setChecked( pSettings->mBlinkingUseAlphaTransition ); boxAllowSuppression->setChecked( pSettings->mAllowSuppressingUnreads ); + spinUnreadOpacityLevel->setValue( pSettings->mUnreadOpacityLevel * 100 ); + spinThunderbirdStartDelay->setValue( pSettings->mLaunchThunderbirdDelay ); + boxShowUnreadCount->setChecked( pSettings->mShowUnreadEmailCount ); if ( pSettings->mLaunchThunderbird ) boxStopThunderbirdOnExit->setChecked( pSettings->mExitThunderbirdWhenQuit ); @@ -161,6 +165,9 @@ pSettings->mNewEmailMenuEnabled = boxEnableNewEmail->isChecked(); pSettings->mBlinkingUseAlphaTransition = boxBlinkingUsesAlpha->isChecked(); pSettings->mUseMorkParser = isMorkParserSelected(); + pSettings->mUnreadOpacityLevel = (double) spinUnreadOpacityLevel->value() / 100.0; + pSettings->mLaunchThunderbirdDelay = spinThunderbirdStartDelay->value(); + pSettings->mShowUnreadEmailCount = boxShowUnreadCount->isChecked(); pSettings->mNotificationIcon = btnNotificationIcon->icon().pixmap( pSettings->mIconSize ); @@ -280,9 +287,25 @@ mAccountModel->addAccount( dlg.account(), dlg.color() ); } +void DialogSettings::accountAddMultiple() +{ + QStringList files = QFileDialog::getOpenFileNames( 0, + "Choose one or more MSF files", + "", + "Mail Index (*.msf)" ); + + if ( files.isEmpty() ) + return; + + // Add them all with default color + for ( QString f : files ) + mAccountModel->addAccount( f, btnNotificationColor->color() ); +} + void DialogSettings::accountEdit() { - accountEditIndex( treeAccounts->currentIndex() ); + if ( treeAccounts->currentIndex().isValid() ) + accountEditIndex( treeAccounts->currentIndex() ); } void DialogSettings::accountEditIndex(const QModelIndex &index) @@ -367,6 +390,9 @@ // Hide the thunderbird path as well groupThunderbirdProfilePath->hide(); + + // Show the "add multiple" button + btnAccountAddMultiple->setVisible( true ); } else { @@ -377,6 +403,9 @@ // Trigger hiding/showing the account group profilePathChanged(); + + // Hide the "add multiple" button + btnAccountAddMultiple->setHidden( true ); } // Did we change comparing to settings? diff -Nru birdtray-1.4/src/dialogsettings.h birdtray-1.5/src/dialogsettings.h --- birdtray-1.4/src/dialogsettings.h 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/dialogsettings.h 2019-02-16 07:43:08.000000000 +0000 @@ -38,6 +38,7 @@ // Account buttons void accountAdd(); + void accountAddMultiple(); void accountEdit(); void accountEditIndex( const QModelIndex& index ); void accountRemove(); diff -Nru birdtray-1.4/src/dialogsettings.ui birdtray-1.5/src/dialogsettings.ui --- birdtray-1.4/src/dialogsettings.ui 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/dialogsettings.ui 2019-02-16 07:43:08.000000000 +0000 @@ -6,8 +6,8 @@ 0 0 - 766 - 504 + 576 + 430 @@ -17,7 +17,7 @@ - 5 + 1 false @@ -154,6 +154,16 @@ + + + <html><head/><body><p>If this box is checked, the Birdtray will show the number of unread emails.</p><p><br/></p><p>If it is unchecked, no count will be shown, and you will only know about unread emails because of blinking (or different, if changed) icon.</p></body></html> + + + Show unread count + + + + Different icon when unread: @@ -297,19 +307,6 @@ - - - Qt::Vertical - - - - 20 - 40 - - - - - Add @@ -331,7 +328,14 @@ - + + + Add multiple... + + + + + Qt::Vertical @@ -383,6 +387,22 @@ + + + <html><head/><body><p>When both Thunderbird and Birdtray are set to start with the operating system, this usually results in two copies of Thunderbird being launched. Here you can add a delay before Thunderbird is launched, to prevent this.</p></body></html> + + + second delay + + + with a + + + 60 + + + + false @@ -621,14 +641,14 @@ Advanced - + - - + + Please do not change those settings unless you understand whatt you're doing. @@ -638,65 +658,113 @@ - - - - Path to Thunderbird executable: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Thunderbird window name pattern: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Minimum notification font size: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - points - - - 1 - - - 512 - - - 4 - - + + + + + + Path to Thunderbird executable: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Thunderbird window name pattern: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Minimum notification font size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + points + + + 1 + + + 512 + + + 4 + + + + - + When blinking, use the fade-in/fade-out transition (increases CPU use!) + + + + + + Make the system tray icon + + + + + + + % + + + + + + 100 + + + + + + + opacue when new mail is present + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + @@ -726,16 +794,16 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:8pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Birdtray version [VERSION] compiled at [DATE].</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright (C) 2018 by George Yunaev, <a href="mailto:gyunaev@ulduzsoft.com"><span style=" text-decoration: underline; color:#2980b9;">gyunaev@ulduzsoft.com</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Birdtray is FREE SOFTWARE, which is licensed under General Public License v3. To clarify further, you can use it for any purpose, including commercial, without paying anything. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For those of you who apprericate my work on Birdtray, which is being developed in my free time, you can do it here: <a href="https://paypal.me/ulduzsoft"><span style=" text-decoration: underline; color:#2980b9;">https://paypal.me/ulduzsoft</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; text-decoration: underline; color:#2980b9;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Thank you for your continuous support!</p></body></html> +</style></head><body style=" font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Birdtray version [VERSION] compiled at [DATE].</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Copyright (C) 2018 by George Yunaev, </span><a href="mailto:gyunaev@ulduzsoft.com"><span style=" font-size:8pt; text-decoration: underline; color:#2980b9;">gyunaev@ulduzsoft.com</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Birdtray is FREE SOFTWARE, which is licensed under General Public License v3. To clarify further, you can use it for any purpose, including commercial, without paying anything. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">For those of you who apprericate my work on Birdtray, which is being developed in my free time, you can do it here: </span><a href="https://paypal.me/ulduzsoft"><span style=" font-size:8pt; text-decoration: underline; color:#2980b9;">https://paypal.me/ulduzsoft</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#2980b9;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Thank you for your continuous support!</span></p></body></html> true diff -Nru birdtray-1.4/src/main.cpp birdtray-1.5/src/main.cpp --- birdtray-1.4/src/main.cpp 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/main.cpp 2019-02-16 07:43:08.000000000 +0000 @@ -4,6 +4,7 @@ #include "trayicon.h" #include "settings.h" #include "morkparser.h" +#include "utils.h" int main(int argc, char *argv[]) { @@ -15,6 +16,12 @@ return 1; } + if ( argc == 3 && !strcmp( argv[1], "--decode" ) ) + { + printf( "Decoded: %s\n", qPrintable( Utils::decodeIMAPutf7( argv[2] ))); + return 1; + } + if ( !QSystemTrayIcon::isSystemTrayAvailable() ) qFatal( "Sorry, system tray cannot be controlled through this addon on your operating system"); diff -Nru birdtray-1.4/src/modelaccounttree.cpp birdtray-1.5/src/modelaccounttree.cpp --- birdtray-1.4/src/modelaccounttree.cpp 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/modelaccounttree.cpp 2019-02-16 07:43:08.000000000 +0000 @@ -2,13 +2,17 @@ #include "settings.h" #include "modelaccounttree.h" +#include "utils.h" ModelAccountTree::ModelAccountTree( QObject *parent ) : QAbstractItemModel( parent ) { - // Get the current settings - mAccounts = pSettings->mFolderNotificationColors.keys(); - mColors = pSettings->mFolderNotificationColors.values(); + // Get the current settings in proper(stored) order + for ( QString uri : pSettings->mFolderNotificationList ) + { + mAccounts.push_back( uri ); + mColors.push_back( pSettings->mFolderNotificationColors[uri] ); + } } int ModelAccountTree::columnCount(const QModelIndex &) const @@ -24,13 +28,14 @@ if ( role == Qt::DisplayRole ) { if ( index.column() == 0 ) - return mAccounts[index.row()]; + return Utils::decodeIMAPutf7( mAccounts[index.row()] ); else return "uses this color"; } - - if ( role == Qt::BackgroundRole && index.column() == 1 ) + else if ( role == Qt::BackgroundRole && index.column() == 1 ) return QBrush( mColors[index.row()] ); + else if ( role == Qt::ToolTipRole && index.column() == 0 ) + return mAccounts[index.row()]; } return QVariant(); @@ -118,9 +123,11 @@ void ModelAccountTree::applySettings() { pSettings->mFolderNotificationColors.clear(); + pSettings->mFolderNotificationList.clear(); for ( int i = 0; i < mAccounts.size(); i++ ) { + pSettings->mFolderNotificationList.push_back( mAccounts[i] ); pSettings->mFolderNotificationColors[ mAccounts[i] ] = mColors[i]; } } diff -Nru birdtray-1.4/src/modelnewemails.cpp birdtray-1.5/src/modelnewemails.cpp --- birdtray-1.4/src/modelnewemails.cpp 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/modelnewemails.cpp 2019-02-16 07:43:08.000000000 +0000 @@ -74,12 +74,15 @@ void ModelNewEmails::edit(const QModelIndex &idx) { - if ( mNewEmailData[ idx.row() ].edit() ) + if ( idx.isValid() && mNewEmailData[ idx.row() ].edit() ) emit dataChanged( createIndex( idx.row(), 0 ), createIndex( idx.row(), 1 ) ); } void ModelNewEmails::remove(const QModelIndex &idx) { + if ( !idx.isValid() ) + return; + beginRemoveRows( QModelIndex(), idx.row(), idx.row() ); mNewEmailData.removeAt( idx.row() ); endRemoveRows(); diff -Nru birdtray-1.4/src/settings.cpp birdtray-1.5/src/settings.cpp --- birdtray-1.4/src/settings.cpp 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/settings.cpp 2019-02-16 07:43:08.000000000 +0000 @@ -29,6 +29,8 @@ settings.setValue("common/hidewhenstarted", mHideWhenStarted ); settings.setValue("common/hidewhenrestarted", mHideWhenRestarted ); settings.setValue("common/allowsuppressingunread", mAllowSuppressingUnreads ); + settings.setValue("common/launchthunderbirddelay", mLaunchThunderbirdDelay ); + settings.setValue("common/showunreademailcount", mShowUnreadEmailCount ); settings.setValue("advanced/tbcmdline", mThunderbirdCmdLine ); settings.setValue("advanced/tbwindowmatch", mThunderbirdWindowMatch ); @@ -37,12 +39,13 @@ settings.setValue("advanced/notificationfontmaxsize", mNotificationMaximumFontSize ); settings.setValue("advanced/watchfiletimeout", mWatchFileTimeout ); settings.setValue("advanced/blinkingusealpha", mBlinkingUseAlphaTransition ); + settings.setValue("advanced/unreadopacitylevel", mUnreadOpacityLevel ); // Convert the map into settings settings.setValue("accounts/count", mFolderNotificationColors.size() ); int index = 0; - for ( QString uri : mFolderNotificationColors.keys() ) + for ( QString uri : mFolderNotificationList ) { QString entry = "accounts/account" + QString::number( index ); settings.setValue( entry + "Color", mFolderNotificationColors[uri].name() ); @@ -98,6 +101,8 @@ mHideWhenStarted = settings.value("common/hidewhenstarted", false ).toBool(); mHideWhenRestarted = settings.value("common/hidewhenrestarted", false ).toBool(); mAllowSuppressingUnreads = settings.value("common/allowsuppressingunread", false ).toBool(); + mLaunchThunderbirdDelay = settings.value("common/launchthunderbirddelay", 0 ).toInt(); + mShowUnreadEmailCount = settings.value("common/showunreademailcount", true ).toBool(); mThunderbirdCmdLine = settings.value("advanced/tbcmdline", "/usr/bin/thunderbird" ).toString(); mThunderbirdWindowMatch = settings.value("advanced/tbwindowmatch", "- Mozilla Thunderbird" ).toString(); @@ -106,6 +111,7 @@ mUseMorkParser = settings.value("advanced/unreadmorkparser", true ).toBool(); mWatchFileTimeout = settings.value("advanced/watchfiletimeout", 150 ).toUInt(); mBlinkingUseAlphaTransition = settings.value("advanced/blinkingusealpha", false ).toBool(); + mUnreadOpacityLevel = settings.value("advanced/unreadopacitylevel", 0.75 ).toDouble(); mFolderNotificationColors.clear(); @@ -115,7 +121,9 @@ for ( int index = 0; index < total; index++ ) { QString entry = "accounts/account" + QString::number( index ); - mFolderNotificationColors[ settings.value( entry + "URI", "" ).toString() ] = QColor( settings.value( entry + "Color", "" ).toString() ); + QString key = settings.value( entry + "URI", "" ).toString(); + mFolderNotificationColors[ key ] = QColor( settings.value( entry + "Color", "" ).toString() ); + mFolderNotificationList.push_back( key ); } // Load new email data from settings diff -Nru birdtray-1.4/src/settings.h birdtray-1.5/src/settings.h --- birdtray-1.4/src/settings.h 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/settings.h 2019-02-16 07:43:08.000000000 +0000 @@ -37,6 +37,9 @@ // Blinking speed unsigned int mBlinkSpeed; + // Opacity level for the tray icon when unread email is present (0.0-1.0) + double mUnreadOpacityLevel; + // Path to Thunderbird folder QString mThunderbirdFolderPath; @@ -55,6 +58,9 @@ // Whether to launch Thunderbird when the app starts bool mLaunchThunderbird; + // The delay in seconds to launch Thunderbird + int mLaunchThunderbirdDelay; + // Whether to hide Thunderbird window after starting bool mHideWhenStarted; @@ -79,6 +85,9 @@ // Whether to allow suppression of unread emails bool mAllowSuppressingUnreads; + // Whether to show the unread email count + bool mShowUnreadEmailCount; + // Watching file timeout (ms) unsigned int mWatchFileTimeout; @@ -90,8 +99,10 @@ bool mNewEmailMenuEnabled; QList< Setting_NewEmail > mNewEmailData; - // Maps the folder URI or full path (for Mork) to the notification color + // Maps the folder URI or full path (for Mork) to the notification color. + // The original order of strings is stored in mFolderNotificationList (to show in UI) QMap< QString, QColor > mFolderNotificationColors; + QStringList mFolderNotificationList; // Load and save them void save(); diff -Nru birdtray-1.4/src/trayicon.cpp birdtray-1.5/src/trayicon.cpp --- birdtray-1.4/src/trayicon.cpp 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/trayicon.cpp 2019-02-16 07:43:08.000000000 +0000 @@ -30,6 +30,8 @@ mThunderbirdWindowExisted = false; mThunderbirdWindowHide = false; + mThunderbirdStartTime = QDateTime::currentDateTime().addSecs( pSettings->mLaunchThunderbirdDelay ); + mWinTools = WindowTools::create(); // If the settings are not yet configure, pop up the message @@ -169,7 +171,7 @@ } // Do we need to draw the unread counter? - if ( unread > 0 ) + if ( unread > 0 && pSettings->mShowUnreadEmailCount ) { // Find the suitable font size, starting from 4 QString countvalue = QString::number( unread ); @@ -266,7 +268,7 @@ if ( !mThunderbirdWindowExisted ) { // No. Shall we start it? - if ( pSettings->mLaunchThunderbird && !mThunderbirdProcess ) + if ( pSettings->mLaunchThunderbird && !mThunderbirdProcess && mThunderbirdStartTime < QDateTime::currentDateTime() ) { startThunderbird(); @@ -316,13 +318,13 @@ if ( pSettings->mBlinkSpeed != 0 ) { // Flip the opacity - if ( mBlinkingIconOpacity == 0.75 ) - mBlinkingIconOpacity = 0.15; + if ( mBlinkingIconOpacity == pSettings->mUnreadOpacityLevel ) + mBlinkingIconOpacity = 1.0 - pSettings->mUnreadOpacityLevel; else - mBlinkingIconOpacity = 0.75; + mBlinkingIconOpacity = pSettings->mUnreadOpacityLevel; } else - mBlinkingIconOpacity = 0.75; + mBlinkingIconOpacity = pSettings->mUnreadOpacityLevel; } updateIcon(); @@ -432,7 +434,10 @@ void TrayIcon::actionSystrayIconActivated(QSystemTrayIcon::ActivationReason reason) { if ( reason == QSystemTrayIcon::Trigger ) - actionActivate(); + { + if ( pSettings->mShowHideThunderbird ) + actionActivate(); + } } void TrayIcon::createMenu() @@ -553,7 +558,10 @@ mThunderbirdProcess = new QProcess(); connect( mThunderbirdProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(tbProcessFinished(int,QProcess::ExitStatus)) ); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) connect( mThunderbirdProcess, &QProcess::errorOccurred, this, &TrayIcon::tbProcessError ); +#endif mThunderbirdProcess->start( pSettings->mThunderbirdCmdLine ); } diff -Nru birdtray-1.4/src/trayicon.h birdtray-1.5/src/trayicon.h --- birdtray-1.4/src/trayicon.h 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/trayicon.h 2019-02-16 07:43:08.000000000 +0000 @@ -96,6 +96,9 @@ // Current status QString mCurrentStatus; + // Time when Thunderbird could be started + QDateTime mThunderbirdStartTime; + // If true, Thunderbird window existed anytime before, but not necessarily now // (we use this to distinguish between start and restart) bool mThunderbirdWindowExisted; diff -Nru birdtray-1.4/src/unreadcounter.cpp birdtray-1.5/src/unreadcounter.cpp --- birdtray-1.4/src/unreadcounter.cpp 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/unreadcounter.cpp 2019-02-16 07:43:08.000000000 +0000 @@ -254,9 +254,9 @@ MorkParser parser; if ( !parser.open( path ) ) - return -1; + return 0; - int unread = 0; + unsigned int unread = 0; // First we parse the unreadChildren column (generic view) const MorkRowMap * rows = parser.rows( 0x80, 0, 0x80 ); @@ -273,9 +273,13 @@ if ( columnName == "unreadChildren" ) { - unsigned int value = parser.getValue(cells[colid ]).toInt( nullptr, 16 ); - unread += value; - } + bool correct; + unsigned int value = parser.getValue(cells[colid ]).toUInt( &correct, 16 ); + + if ( correct ) + unread += value; + else + qDebug("Incorrect Mork value: %s", qPrintable( parser.getValue(cells[colid ]) )); } } } } @@ -296,8 +300,13 @@ if ( columnName == "numNewMsgs" ) { - unsigned int value = parser.getValue(cells[colid ]).toInt( nullptr, 16 ); - unread += value; + bool correct; + unsigned int value = parser.getValue(cells[colid ]).toInt( &correct, 16 ); + + if ( correct ) + unread += value; + else + qDebug("Incorrect Mork value: %s", qPrintable( parser.getValue(cells[colid ]) )); } } } diff -Nru birdtray-1.4/src/utils.cpp birdtray-1.5/src/utils.cpp --- birdtray-1.4/src/utils.cpp 1970-01-01 00:00:00.000000000 +0000 +++ birdtray-1.5/src/utils.cpp 2019-02-16 07:43:08.000000000 +0000 @@ -0,0 +1,112 @@ +#include "utils.h" +#include + + +QString Utils::decodeIMAPutf7(const QString ¶m) +{ + // See https://tools.ietf.org/html/rfc2060#page-13 + // By convention, international mailbox names are specified using a + // modified version of the UTF-7 encoding described in [UTF-7]. The + // purpose of these modifications is to correct the following problems + // with UTF-7: + // + // 1) UTF-7 uses the "+" character for shifting; this conflicts with + // the common use of "+" in mailbox names, in particular USENET + // newsgroup names. + // + // 2) UTF-7's encoding is BASE64 which uses the "/" character; this + // conflicts with the use of "/" as a popular hierarchy delimiter. + // + // 3) UTF-7 prohibits the unencoded usage of "\"; this conflicts with + // the use of "\" as a popular hierarchy delimiter. + // + // 4) UTF-7 prohibits the unencoded usage of "~"; this conflicts with + // the use of "~" in some servers as a home directory indicator. + // + // 5) UTF-7 permits multiple alternate forms to represent the same + // string; in particular, printable US-ASCII chararacters can be + // represented in encoded form. + // + // In modified UTF-7, printable US-ASCII characters except for "&" + // represent themselves; that is, characters with octet values 0x20-0x25 + // and 0x27-0x7e. The character "&" (0x26) is represented by the two- + // octet sequence "&-". + // + // All other characters (octet values 0x00-0x1f, 0x7f-0xff, and all + // Unicode 16-bit octets) are represented in modified BASE64, with a + // further modification from [UTF-7] that "," is used instead of "/". + // Modified BASE64 MUST NOT be used to represent any printing US-ASCII + // character which can represent itself. + // + // "&" is used to shift to modified BASE64 and "-" to shift back to US- + // ASCII. All names start in US-ASCII, and MUST end in US-ASCII (that + // is, a name that ends with a Unicode 16-bit octet MUST end with a "- + // "). + QString out; + QString decodebuf; + bool decoding = false; + QTextCodec * codec = QTextCodec::codecForName("UTF16-BE"); + + // This is extremely unlikely but still... + if ( !codec ) + return "ERROR1-" + param; + + for ( int i = 0; i < param.length(); i++ ) + { + // Are we already decoding? + if ( decoding ) + { + if ( param[i] == '-' ) + { + // Decode this string as modified UTF7, which is UTF16BE encoded in base64 + QByteArray utf16data = QByteArray::fromBase64( qPrintable( decodebuf ) ); + + if ( utf16data.isEmpty() ) + { + // Print the warning, and return an error + qWarning("Invalid IMAP UTF7 sequence: '%s' contains invalid base64 '%s' - please report", qPrintable(param), qPrintable(decodebuf) ); + return "ERROR2-" + param; + } + + // Decode it as UTF16 + out += codec->toUnicode( utf16data ); + + // And reset the remaining + decodebuf.clear(); + decoding = false; + } + else + { + // This is modified BASE64 where "," is used instead of "/" + if ( param[i] == ',' ) + decodebuf.append( '/' ); + else + decodebuf.append( param[i] ); + } + } + else + { + // We are not decoding yet; & indicates possible start of decoding + if ( param[i] == '&' ) + { + // this is either start of decoding or &- + if ( i + 2 < param.length() && param[i+1] == '-' ) + { + // This is "&-" combination which means &, and does not start decoding + i++; + out.append( '&' ); + } + else + decoding = true; + } + else + out.append( param[i] ); + } + } + + // The string MUST end with '-' and thus there should be nothing in the decodebuf + if ( !decodebuf.isEmpty() ) + qWarning("Invalid IMAP UTF7 sequence: '%s' may be decoded incorrectly", qPrintable(param) ); + + return out; +} diff -Nru birdtray-1.4/src/utils.h birdtray-1.5/src/utils.h --- birdtray-1.4/src/utils.h 1970-01-01 00:00:00.000000000 +0000 +++ birdtray-1.5/src/utils.h 2019-02-16 07:43:08.000000000 +0000 @@ -0,0 +1,13 @@ +#ifndef UTILS_H +#define UTILS_H + +#include + +class Utils +{ + public: + // Decodes IMAP UTF7 data + static QString decodeIMAPutf7( const QString& param ); +}; + +#endif // UTILS_H diff -Nru birdtray-1.4/src/version.h birdtray-1.5/src/version.h --- birdtray-1.4/src/version.h 2018-12-01 14:27:49.000000000 +0000 +++ birdtray-1.5/src/version.h 2019-02-16 07:43:08.000000000 +0000 @@ -2,6 +2,6 @@ #define VERSION_H static const unsigned int VERSION_MAJOR = 1; -static const unsigned int VERSION_MINOR = 4; +static const unsigned int VERSION_MINOR = 5; #endif // VERSION_H