diff -Nru kdepim-4.12.97/agents/folderarchiveagent.desktop kdepim-4.13.0/agents/folderarchiveagent.desktop --- kdepim-4.12.97/agents/folderarchiveagent.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/agents/folderarchiveagent.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -39,6 +39,14 @@ Comment[de]=Der Agent zur Ordner-Archivierung ermöglicht das Speichern von E-Mails in angegebenen Archivordnern Comment[el]=Ο πράκτορας φακέλου αρχειοθέτησης σας επιτρέπει να αποθηκεύετε μηνύματα ηλ. αλληλογραφίας σε έναν συγκεκριμένο φάκελο αρχειοθέτησης Comment[es]=El agente de archivado de carpeta permite almacenar correos en una carpeta de archivos específica +Comment[fi]=Kansioiden arkistointiagentti mahdollistaa postien tallettamisen erityisiin arkistokansioihin +Comment[fr]=L'agent d'archivage de dossiers permet de stocker des courriers électroniques dans un dossier d'archive +Comment[gl]=O Axente de Arquivo de Cartafoles permite almacenar o correo nun cartafol de arquivo específico +Comment[hu]=A mappaarchiváló ügynök lehetővé teszi e-mailek tárolását a megadott archívum mappában +Comment[ia]=Agente de archivar dossier permitte immagasinar messages de e-posta in un specific dossier +Comment[it]=L'agente di archiviazione per cartella permette di memorizzazar i messaggi di posta in specifiche cartelle di archiviazione +Comment[kk]=Қапшық архивтеу агенті тиісті архив қапшықта поштаны сақтап береді +Comment[nb]=Postarkiv-agenten kan lagre e-poster i en bestemt arkivmappe Comment[nds]=De Orner-Archiveerhölper sekert Nettpost binnen en fastleggt Archievorner Comment[nl]=Agent voor archiveren van map stelt u in staat om e-mailberichten op te slaan in een archiefmap Comment[pl]=Agent archiwizacji katalogu pozwala na przechowywanie poczty w określonym katalogu archiwum diff -Nru kdepim-4.12.97/agents/followupreminderagent/akonadi_followupreminder_agent.notifyrc kdepim-4.13.0/agents/followupreminderagent/akonadi_followupreminder_agent.notifyrc --- kdepim-4.12.97/agents/followupreminderagent/akonadi_followupreminder_agent.notifyrc 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/agents/followupreminderagent/akonadi_followupreminder_agent.notifyrc 2014-04-10 07:40:20.000000000 +0000 @@ -13,6 +13,7 @@ Comment[gl]=Axente de lembranzas de seguimento Comment[hu]=Nyomkövető emlékeztető ügynök Comment[ia]=Agente de memorar de continuation (Followup Reminder Agent) +Comment[it]=Agente per gli avvisi delle azioni da seguire Comment[kk]=Жауап беру туралы ескерту агенті Comment[nb]=Agent for påminnelse om oppfølging Comment[nds]=Antwoortnaricht-Anstoothölper diff -Nru kdepim-4.12.97/agents/followupreminderagent/followupreminder.desktop kdepim-4.13.0/agents/followupreminderagent/followupreminder.desktop --- kdepim-4.12.97/agents/followupreminderagent/followupreminder.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/agents/followupreminderagent/followupreminder.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -12,6 +12,7 @@ Name[gl]=Axente de lembranzas de seguimento Name[hu]=Nyomkövető emlékeztető ügynök Name[ia]=Followup Reminder Agent +Name[it]=Agente per gli avvisi delle azioni da seguire Name[kk]=Жауап беру туралы ескерту агенті Name[nb]=Agent for påminnelse om oppfølging Name[nds]=Antwoortnaricht-Anstoothölper @@ -43,6 +44,7 @@ Comment[gl]=O Axente de lembranzas de seguimento permite lembrarlle cando non se respondeu a unha mensaxe de correo. Comment[hu]=A Nyomkövető emlékeztető ügynök lehetővé teszi, hogy emlékeztesse önt, ha egy levél nem lett megválaszolva. Comment[ia]=Follorwup Reminder Agent permitte te de memorar te quando un message de e-posta esseva sin responsa. +Comment[it]=L'agente per gli avvisi delle azioni da seguire permette di avvisarti quando un messaggio di posta non ha avuto una risposta. Comment[kk]=Жауап беру туралы ескерту агенті эл.поштаға жауап берілмегеніңізді ескереді. Comment[nb]=Agenten for påminnelse om oppfølging kan minne deg om at det ikke er sendt svar på en e-post. Comment[nds]=De Antwoortnaricht-Anstoothölper stööt Di an, wenn Du op en Nettbreef noch nich antert hest. diff -Nru kdepim-4.12.97/agents/notesagent/akonadi_notes_agent.notifyrc kdepim-4.13.0/agents/notesagent/akonadi_notes_agent.notifyrc --- kdepim-4.12.97/agents/notesagent/akonadi_notes_agent.notifyrc 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/agents/notesagent/akonadi_notes_agent.notifyrc 2014-04-10 07:40:20.000000000 +0000 @@ -13,12 +13,14 @@ Comment[fr]=Agent pour les notes Comment[hu]=Jegyzetek ügynök Comment[ia]=Agente de Notas +Comment[it]=Agente delle note Comment[nb]=Notatagent Comment[nds]=Notizenhölper Comment[nl]=Agent voor notities Comment[pl]=Agent notatek Comment[pt]=Agente de Notas Comment[pt_BR]=Agente de Notas +Comment[ru]=Агент заметок Comment[sk]=Agent poznámok Comment[sr]=Агент бележака Comment[sr@ijekavian]=Агент бележака @@ -42,12 +44,14 @@ Name[fr]=Note reçue Name[hu]=Fogadott egy jegyzet Name[ia]=Il ha recipite un nota +Name[it]=Nota ricevuta Name[nb]=Mottatt et notat Name[nds]=Notiz kregen Name[nl]=Er is een notitie ontvangen Name[pl]=Otrzymano notatkę Name[pt]=Nota recebida Name[pt_BR]=Nota recebida +Name[ru]=Получена заметка Name[sk]=Prijatá poznámka Name[sr]=Примљена белешка Name[sr@ijekavian]=Примљена белешка diff -Nru kdepim-4.12.97/agents/notesagent/notesagent.desktop kdepim-4.13.0/agents/notesagent/notesagent.desktop --- kdepim-4.12.97/agents/notesagent/notesagent.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/agents/notesagent/notesagent.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -12,12 +12,14 @@ Name[fr]=Agent pour les notes Name[hu]=Jegyzetek ügynök Name[ia]=Agente de Notas (Notes Agent) +Name[it]=Agente delle note Name[nb]=Notatagent Name[nds]=Notizenhölper Name[nl]=Agent voor notities Name[pl]=Agent notatek Name[pt]=Agente de Notas Name[pt_BR]=Agente de Notas +Name[ru]=Агент заметок Name[sk]=Agent poznámok Name[sr]=Агент бележака Name[sr@ijekavian]=Агент бележака @@ -39,12 +41,14 @@ Comment[fr]=Ajoute les notes reçus par le réseau et gère les notifications d'alarme Comment[hu]=Hálózatról fogadott jegyzeteket ad hozzá és kezeli a jegyzetriasztási értesítéseket Comment[ia]=Adde notas recipite via rete e manea notificationes de nota de alarma +Comment[it]=Aggiunge le note ricevute via rete e gestisce le notifiche di avvisi delle note Comment[nb]=Legger til notater mottatt over nettverket og behandler notatvarslinger Comment[nds]=Föögt Notizen över't Nettwark to un gifft över Alarmnotizen Bescheed Comment[nl]=Voegt notities toe ontvangen via het netwerk en behandelt meldingen over herinneringen voor notities Comment[pl]=Dodaje notatki otrzymywane przez sieć i obsługuje alarmy notatek Comment[pt]=Adiciona as notas recebidas pela rede e lida com as notificações dos alarmes das notas Comment[pt_BR]=Adiciona notas recebidas via rede e lida com as notificações de alarme das notas +Comment[ru]=Добавляет заметки, полученные по сети, и обрабатывает встроенные в них напоминания Comment[sk]=Pridá poznámky prijaté cez sieť a spracuje upozornenia výstrah poznámok Comment[sr]=Додаје белешке примљене преко мреже и обрађује обавештења аларма бележака Comment[sr@ijekavian]=Додаје белешке примљене преко мреже и обрађује обавештења аларма бележака diff -Nru kdepim-4.12.97/agents/sendlateragent/sendlaterconfiguredialog.cpp kdepim-4.13.0/agents/sendlateragent/sendlaterconfiguredialog.cpp --- kdepim-4.12.97/agents/sendlateragent/sendlaterconfiguredialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/agents/sendlateragent/sendlaterconfiguredialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -147,7 +147,6 @@ << i18n("Send around") << i18n("Recurrent") << i18n("Message Id"); - //TODO add more infos ? Tooltip about message for example ? with nepomuk as in messagelist ? mWidget->treeWidget->setHeaderLabels(headers); mWidget->treeWidget->setSortingEnabled(true); diff -Nru kdepim-4.12.97/blogilo/src/main.cpp kdepim-4.13.0/blogilo/src/main.cpp --- kdepim-4.12.97/blogilo/src/main.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/blogilo/src/main.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -55,6 +55,7 @@ KGlobal::locale()->insertCatalog(QLatin1String("libkxmlrpcclient")); KGlobal::locale()->insertCatalog(QLatin1String("libcomposereditorng")); KGlobal::locale()->insertCatalog(QLatin1String("libpimcommon")); + KGlobal::locale()->insertCatalog(QLatin1String("libkgapi")); MainWindow *bilbo = new MainWindow; diff -Nru kdepim-4.12.97/blogilo/src/storageservice/storageservicemanagersettingsjob.cpp kdepim-4.13.0/blogilo/src/storageservice/storageservicemanagersettingsjob.cpp --- kdepim-4.12.97/blogilo/src/storageservice/storageservicemanagersettingsjob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/blogilo/src/storageservice/storageservicemanagersettingsjob.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -82,21 +82,11 @@ return QLatin1String("https://bugs.kde.org/"); } -QString StorageServiceManagerSettingsJob::ubuntuOneAttachmentVolume() const -{ - return QLatin1String("/~/KMail Attachments"); -} - QString StorageServiceManagerSettingsJob::hubicScope() const { return QLatin1String("usage.r,account.r,credentials.r,links.wd"); } -QString StorageServiceManagerSettingsJob::ubuntuOneTokenName() const -{ - return QLatin1String("kde storagemanager"); -} - QString StorageServiceManagerSettingsJob::gdriveClientId() const { return QLatin1String("735222197981-mrcgtaqf05914buqjkts7mk79blsquas.apps.googleusercontent.com"); diff -Nru kdepim-4.12.97/blogilo/src/storageservice/storageservicemanagersettingsjob.h kdepim-4.13.0/blogilo/src/storageservice/storageservicemanagersettingsjob.h --- kdepim-4.12.97/blogilo/src/storageservice/storageservicemanagersettingsjob.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/blogilo/src/storageservice/storageservicemanagersettingsjob.h 2014-04-10 07:40:20.000000000 +0000 @@ -40,9 +40,7 @@ QString hubicClientSecret() const; QString dropboxRootPath() const; QString oauth2RedirectUrl() const; - QString ubuntuOneAttachmentVolume() const; QString hubicScope() const; - QString ubuntuOneTokenName() const; QString gdriveClientId() const; QString gdriveClientSecret() const; QString defaultUploadFolder() const; diff -Nru kdepim-4.12.97/calendarsupport/attachmenthandler.cpp kdepim-4.13.0/calendarsupport/attachmenthandler.cpp --- kdepim-4.12.97/calendarsupport/attachmenthandler.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/calendarsupport/attachmenthandler.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -1,6 +1,7 @@ /* Copyright (c) 2010 Klarlvdalens Datakonsult AB, a KDAB Group company Author: Allen Winter + Copyright (C) 2014 Sergio Martins This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -28,8 +29,9 @@ @author Allen Winter \ */ #include "attachmenthandler.h" -#include "next/incidencesearchjob.h" +#include "calendarsupport/utils.h" +#include #include #include #include @@ -44,6 +46,7 @@ #include using namespace KCalCore; +using namespace Akonadi; namespace CalendarSupport { @@ -195,9 +198,9 @@ void AttachmentHandler::view( const QString &attachmentName, const QString &uid ) { - IncidenceSearchJob *job = new IncidenceSearchJob(); - job->setQuery( CalendarSupport::IncidenceSearchJob::IncidenceUid, uid, - IncidenceSearchJob::ExactMatch ); + Item item; + item.setGid(uid); + ItemFetchJob *job = new ItemFetchJob(item); connect( job, SIGNAL(result(KJob*)), this, SLOT(slotFinishView(KJob*)) ); ReceivedInfo info; info.attachmentName = attachmentName; @@ -257,9 +260,9 @@ void AttachmentHandler::saveAs( const QString &attachmentName, const QString &uid ) { - IncidenceSearchJob *job = new IncidenceSearchJob(); - job->setQuery( CalendarSupport::IncidenceSearchJob::IncidenceUid, uid, - IncidenceSearchJob::ExactMatch ); + Item item; + item.setGid(uid); + ItemFetchJob *job = new ItemFetchJob(item); connect( job, SIGNAL(result(KJob*)), this, SLOT(slotFinishView(KJob*)) ); ReceivedInfo info; @@ -276,15 +279,20 @@ void AttachmentHandler::slotFinishSaveAs( KJob *job ) { - IncidenceSearchJob *searchJob = qobject_cast( job ); - const KCalCore::Incidence::List incidences = searchJob->incidences(); ReceivedInfo info = d->mJobToReceivedInfo[job]; - bool success = false; - if ( !incidences.isEmpty() ) { - if ( saveAs( info.attachmentName, incidences.first() ) ) { - success = true; + + if ( job->error() != 0 ) { + ItemFetchJob *fetchJob = qobject_cast( job ); + const Item::List items = fetchJob->items(); + if ( !items.isEmpty() ) { + Incidence::Ptr incidence = CalendarSupport::incidence( items.first() ); + success = incidence && saveAs( info.attachmentName, incidence ); + } else { + kWarning() << Q_FUNC_INFO << "No item found"; } + } else { + kWarning() << Q_FUNC_INFO << "Job error:" << job->errorString(); } emit saveAsFinished( info.uid, info.attachmentName, success ); @@ -293,15 +301,20 @@ void AttachmentHandler::slotFinishView( KJob *job ) { - IncidenceSearchJob *searchJob = qobject_cast( job ); - const KCalCore::Incidence::List incidences = searchJob->incidences(); ReceivedInfo info = d->mJobToReceivedInfo[job]; - bool success = false; - if ( !incidences.isEmpty() ) { - if ( view( info.attachmentName, incidences.first() ) ) { - success = true; + + if ( job->error() != 0 ) { + ItemFetchJob *fetchJob = qobject_cast( job ); + const Item::List items = fetchJob->items(); + if ( !items.isEmpty() ) { + Incidence::Ptr incidence = CalendarSupport::incidence( items.first() ); + success = incidence && view( info.attachmentName, incidence ); + } else { + kWarning() << Q_FUNC_INFO << "No item found"; } + } else { + kWarning() << Q_FUNC_INFO << "Job error:" << job->errorString(); } emit viewFinished( info.uid, info.attachmentName, success ); diff -Nru kdepim-4.12.97/calendarsupport/calendarsingleton.cpp kdepim-4.13.0/calendarsupport/calendarsingleton.cpp --- kdepim-4.12.97/calendarsupport/calendarsingleton.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/calendarsupport/calendarsingleton.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -28,12 +28,6 @@ #include -/** - * Singleton is implemented through qApp parenting because we can't rely on K_GLOBAL_STATIC. - * - * QWidgets and QAbstractItemModels can't be global because their dtor depends on other globals - * and the order of global destruction is undefined. - */ Akonadi::ETMCalendar* CalendarSupport::calendarSingleton() { static Akonadi::ETMCalendar *calendar = 0; diff -Nru kdepim-4.12.97/calendarsupport/calendarsingleton.h kdepim-4.13.0/calendarsupport/calendarsingleton.h --- kdepim-4.12.97/calendarsupport/calendarsingleton.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/calendarsupport/calendarsingleton.h 2014-04-10 07:40:20.000000000 +0000 @@ -34,8 +34,6 @@ /** * ETMCalendar to be used by kontact plugins to avoid having * 3 loaded calendars which occupy lots of memory. - * - * KOrganizer itself can't use this one since it disables calendar selection filtering. */ CALENDARSUPPORT_EXPORT Akonadi::ETMCalendar* calendarSingleton(); } diff -Nru kdepim-4.12.97/calendarsupport/CMakeLists.txt kdepim-4.13.0/calendarsupport/CMakeLists.txt --- kdepim-4.12.97/calendarsupport/CMakeLists.txt 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/calendarsupport/CMakeLists.txt 2014-04-10 07:40:20.000000000 +0000 @@ -39,7 +39,6 @@ printing/yearprint.cpp next/incidencefetchjob.cpp - next/incidencesearchjob.cpp next/incidenceviewer.cpp ) diff -Nru kdepim-4.12.97/calendarsupport/next/incidencesearchjob.cpp kdepim-4.13.0/calendarsupport/next/incidencesearchjob.cpp --- kdepim-4.12.97/calendarsupport/next/incidencesearchjob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/calendarsupport/next/incidencesearchjob.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -/* - Copyright (c) 2009 Tobias Koenig - - Copyright (c) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company - Author: Sérgio Martins - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#include "incidencesearchjob.h" - -#include - -using namespace CalendarSupport; -using namespace Akonadi; - -class IncidenceSearchJob::Private -{ - public: - int mLimit; -}; - -IncidenceSearchJob::IncidenceSearchJob( QObject *parent ) - : ItemSearchJob( QString(), parent ), d( new Private() ) -{ - fetchScope().fetchFullPayload(); - d->mLimit = -1; - - // by default search for all incidences - ItemSearchJob::setQuery( QLatin1String( QByteArray(QByteArray("prefix ncal:" - "prefix nao:" - "SELECT DISTINCT ?r WHERE" - "{" - "?subclasses rdfs:subClassOf ncal:UnionOfEventJournalTodo ." - "?r a ?subclasses ." - "?r nao:hasSymbol \"view-pim-calendar\"^^ ." - "?r <") + akonadiItemIdUri().toEncoded() + QByteArray("> ?itemId . " - "}") - ) ) ); -} - -IncidenceSearchJob::~IncidenceSearchJob() -{ - delete d; -} - -void IncidenceSearchJob::setQuery( Criterion criterion, const QString &value, Match match ) -{ - if ( match == StartsWithMatch && value.size() < 4 ) { - match = ExactMatch; - } - - QString query = QString::fromLatin1( "prefix ncal: " ); - - if ( match == ExactMatch ) { - if ( criterion == IncidenceUid ) { - query += QString::fromLatin1( - QByteArray(QByteArray("SELECT ?r WHERE {" - "?subclasses rdfs:subClassOf ncal:UnionOfEventJournalTodo ." - "?r a ?subclasses ." - "?r nao:hasSymbol \"view-pim-calendar\"^^ ." - "?r ncal:uid \"%1\"^^ ." - "?r <") + akonadiItemIdUri().toEncoded() + QByteArray("> ?itemId . " - "}") ) - ); - } - } else if ( match == StartsWithMatch ) { - if ( criterion == IncidenceUid ) { - query += QString::fromLatin1( - QByteArray(QByteArray("SELECT ?r WHERE" - "{" - "?subclasses rdfs:subClassOf ncal:UnionOfEventJournalTodo ." - "?r a ?subclasses ." - "?r ncal:uid ?uid ." - "?r nao:hasSymbol \"view-pim-calendar\"^^ ." - "?r <") + akonadiItemIdUri().toEncoded() + QByteArray("> ?itemId . " - "FILTER REGEX( ?uid, \"^%1\", 'i')" - "}") ) - ); - } - } else if ( match == ContainsMatch ) { - if ( criterion == IncidenceUid ) { - query += QString::fromLatin1( - QByteArray(QByteArray("SELECT ?r WHERE" - "{" - "?subclasses rdfs:subClassOf ncal:UnionOfEventJournalTodo ." - "?r a ?subclasses ." - "?r ncal:uid ?uid ." - "?r nao:hasSymbol \"view-pim-calendar\"^^ ." - "?r <") + akonadiItemIdUri().toEncoded() + QByteArray("> ?itemId . " - "FILTER REGEX( ?uid, \"%1\", 'i')" - "}") ) - ); - } - } - - if ( d->mLimit != -1 ) { - query += QString::fromLatin1( " LIMIT %1" ).arg( d->mLimit ); - } - query = query.arg( value ); - ItemSearchJob::setQuery( query ); -} - -void IncidenceSearchJob::setLimit( int limit ) -{ - d->mLimit = limit; -} - -KCalCore::Incidence::List IncidenceSearchJob::incidences() const -{ - KCalCore::Incidence::List incidences; - - foreach ( const Item &item, items() ) { - if ( item.hasPayload() ) { - incidences.append( item.payload() ); - } - } - - return incidences; -} - diff -Nru kdepim-4.12.97/calendarsupport/next/incidencesearchjob.h kdepim-4.13.0/calendarsupport/next/incidencesearchjob.h --- kdepim-4.12.97/calendarsupport/next/incidencesearchjob.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/calendarsupport/next/incidencesearchjob.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,152 +0,0 @@ -/* - Copyright (c) 2009 Tobias Koenig - - Copyright (c) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company - Author: Sérgio Martins - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#ifndef CALENDARSUPPORT_INCIDENCESEARCHJOB_H -#define CALENDARSUPPORT_INCIDENCESEARCHJOB_H - -#include "calendarsupport_export.h" - -#include -#include - -#include - -namespace CalendarSupport { - -/** - * @short Job that searches for calendar incidences in the Akonadi storage. - * - * This job searches for calendar incidences (events, to-dos and journals) that match given search - * criteria and return the list of incidences. - * - * Examples: - * - * @code - * - * // Search all incidences with uid 1234 - * CalendarSupport::IncidenceSearchJob *job = new CalendarSupport::IncidenceSearchJob(); - * job->setQuery( CalendarSupport::IncidenceSearchJob::IncidenceUid, "1234", - * CalendarSupport::IncidenceSearchJob::ExactMatch ); - * connect( job, SIGNAL( result( KJob* ) ), this, SLOT( searchResult( KJob* ) ) ); - * - * ... - * - * MyClass::searchResult( KJob *job ) - * { - * CalendarSupport::IncidenceSearchJob *searchJob = - * qobject_cast( job ); - * const KCalCore::Incidence::List incidences = searchJob->incidences(); - * // do something with the incidences - * } - * - * @endcode - * - * @code - * - * // Search for all existing incidences - * CalendarSupport::IncidenceSearchJob *job = new CalendarSupport::IncidenceSearchJob(); - * connect( job, SIGNAL( result( KJob* ) ), this, SLOT( searchResult( KJob* ) ) ); - * - * ... - * - * MyClass::searchResult( KJob *job ) - * { - * CalendarSupport::IncidenceSearchJob *searchJob = - * qobject_cast( job ); - * const KCalCore::Incidence::List incidences = searchJob->incidences(); - * // do something with the incidences - * } - * - * @endcode - * - * @author Tobias Koenig - * @author Sérgio Martins - * @since 4.6 - */ -class CALENDARSUPPORT_EXPORT IncidenceSearchJob : public Akonadi::ItemSearchJob -{ - Q_OBJECT - - public: - /** - * Creates a new incidence search job. - * - * @param parent The parent object. - */ - explicit IncidenceSearchJob( QObject *parent = 0 ); - - /** - * Destroys the incidence search job. - */ - ~IncidenceSearchJob(); - - /** - * Describes the criteria that can be searched for. - */ - enum Criterion { - IncidenceUid ///< The global unique identifier of the incidence. @since 4.6 - }; - - /** - * Describes the type of pattern matching that shall be used. - * - * @since 4.6 - */ - enum Match { - ExactMatch, ///< The result must match exactly the pattern (case sensitive). - StartsWithMatch, ///< The result must start with the pattern (case insensitive). - ContainsMatch ///< The result must contain the pattern (case insensitive). - }; - - /** - * Sets the @p criterion and @p value for the search with @p match. - * - * @since 4.6 - */ - void setQuery( Criterion criterion, const QString &value, Match match ); - - /** - * Sets a @p limit on how many results will be returned by this search job. - * This is useful in situation where for example only the first search result is needed anyway, - * setting a limit of 1 here will greatly reduce the resource usage of Nepomuk during the - * search. - * - * This needs to be called before calling setQuery() to have an effect. - * By default, the number of results is unlimited. - */ - void setLimit( int limit ); - - /** - * Returns the incidences that matched the search criteria. - */ - KCalCore::Incidence::List incidences() const; - - private: - //@cond PRIVATE - class Private; - Private *const d; - //@endcond -}; - -} - -#endif diff -Nru kdepim-4.12.97/calendarsupport/tests/CMakeLists.txt kdepim-4.13.0/calendarsupport/tests/CMakeLists.txt --- kdepim-4.12.97/calendarsupport/tests/CMakeLists.txt 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/calendarsupport/tests/CMakeLists.txt 2014-04-10 07:40:20.000000000 +0000 @@ -1,15 +1 @@ include_directories(${CMAKE_SOURCE_DIR}/calendarsupport) - -set(incidencesearcher_SRC - incidencesearcher.cpp -) - -kde4_add_executable(incidencesearcher ${incidencesearcher_SRC}) - -target_link_libraries(incidencesearcher - calendarsupport - ${KDEPIMLIBS_AKONADI_LIBS} - ${QT_QTGUI_LIBRARY} - ${KDE4_KDEUI_LIBS} - ${KDEPIMLIBS_KCALCORE_LIBS} -) diff -Nru kdepim-4.12.97/calendarsupport/tests/incidencesearcher.cpp kdepim-4.13.0/calendarsupport/tests/incidencesearcher.cpp --- kdepim-4.12.97/calendarsupport/tests/incidencesearcher.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/calendarsupport/tests/incidencesearcher.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,113 +0,0 @@ -/* - Copyright (c) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company - Author: Sérgio Martins - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#include "incidencesearcher.h" - -#include "../next/incidencesearchjob.h" - -#include - -#include -#include - -#include - -using namespace CalendarSupport; -using namespace Akonadi; - -IncidenceSearcher::IncidenceSearcher( const QString &uid ) -{ - // Exact Match - IncidenceSearchJob *job1 = new IncidenceSearchJob(); - job1->setQuery( CalendarSupport::IncidenceSearchJob::IncidenceUid, uid, - IncidenceSearchJob::ExactMatch ); - connect( job1, SIGNAL(result(KJob*)), this, SLOT(finished(KJob*)) ); - - // StartsWithMatch - IncidenceSearchJob *job2 = new IncidenceSearchJob(); - job2->setQuery( IncidenceSearchJob::IncidenceUid, uid, - IncidenceSearchJob::StartsWithMatch ); - connect( job2, SIGNAL(result(KJob*)), this, SLOT(finished(KJob*)) ); - - // ContainsMatch - IncidenceSearchJob *job3 = new IncidenceSearchJob(); - job3->setQuery( IncidenceSearchJob::IncidenceUid, uid, - IncidenceSearchJob::ContainsMatch ); - connect( job3, SIGNAL(result(KJob*)), this, SLOT(finished(KJob*)) ); - - // No query - IncidenceSearchJob *job4 = new IncidenceSearchJob(); - connect( job4, SIGNAL(result(KJob*)), this, SLOT(finished(KJob*)) ); - - mJobs << job1 << job2 << job3 << job4; -} - -void IncidenceSearcher::finished( KJob *job ) -{ - static int count = 0; - ++count; - - Q_ASSERT( !job->error() ); - - IncidenceSearchJob *searchJob = qobject_cast( job ); - - const KCalCore::Incidence::List incidences = searchJob->incidences(); - QStringList matches; - matches << QLatin1String( "ExactMatch" ) - << QLatin1String( "StartsWithMatch" ) - << QLatin1String( "ContainsMatch" ) - << QLatin1String( "No query" ); - - qDebug() << "Found " << incidences.count() << " incidences using " << - matches[mJobs.indexOf( job )]; - - if ( !incidences.isEmpty() ) { - qDebug() << "Incidences are:"; - foreach( const KCalCore::Incidence::Ptr &incidence, incidences ) { - if ( incidence ) { - qDebug() << "Summary = " << incidence->summary() << "; uid = " - << incidence->uid() << "; schedulingId = " << incidence->schedulingID(); - } - } - } - - - if ( count == 4 ) { - qDebug() << "Finished"; - qApp->quit(); - } -} - -int main( int argc, char* argv[] ) -{ - KCmdLineOptions options; - options.add( "+uid", ki18n( "Incidence uid to search for" ) ); - KCmdLineArgs::addCmdLineOptions( options ); - KCmdLineArgs::init( argc, argv, "IncidenceSearchJob", 0, - ki18n("IncidenceSearcher") ,"0.1" ,ki18n("IncidenceSearchJob demo") ); - - KApplication app( false ); - KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); - - IncidenceSearcher is( args->arg( 0 ) ); - - return app.exec(); -} - diff -Nru kdepim-4.12.97/calendarsupport/tests/incidencesearcher.h kdepim-4.13.0/calendarsupport/tests/incidencesearcher.h --- kdepim-4.12.97/calendarsupport/tests/incidencesearcher.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/calendarsupport/tests/incidencesearcher.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -/* - Copyright (c) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company - Author: Sérgio Martins - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#ifndef CALENDARSUPPORT_INCIDENCESEARCHER_H -#define CALENDARSUPPORT_INCIDENCESEARCHER_H - -#include -#include - -class KJob; - -class IncidenceSearcher : public QObject -{ - Q_OBJECT - public: - IncidenceSearcher( const QString &uid ); - private Q_SLOTS: - void finished( KJob *j); - private: - QList mJobs; -}; - -#endif diff -Nru kdepim-4.12.97/CMakeLists.txt kdepim-4.13.0/CMakeLists.txt --- kdepim-4.12.97/CMakeLists.txt 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/CMakeLists.txt 2014-04-10 07:40:20.000000000 +0000 @@ -82,7 +82,7 @@ # 3.0, 3.0.1, 3.1 alpha1, 3.1 beta1, 3.1 beta2, 3.1 rc1, 3.1, 3.1.1, 3.2 pre, 3.2 alpha1 # Do NOT add quote -set(KDEPIM_DEV_VERSION rc) +set(KDEPIM_DEV_VERSION) # add an extra space if(DEFINED KDEPIM_DEV_VERSION) @@ -100,7 +100,7 @@ find_package(KDE4 4.12.0 REQUIRED) include(KDE4Defaults) -find_package(KdepimLibs 4.12.97) +find_package(KdepimLibs 4.13.0) set_package_properties(KdepimLibs PROPERTIES DESCRIPTION "The KDEPIM libraries" URL "http://www.kde.org" TYPE REQUIRED) ############### Load the CTest options ############### @@ -166,7 +166,7 @@ # Otherwise... ############### Find the stuff we need ############### # Akonadi - find_package(Akonadi 1.11.80 QUIET CONFIG) + find_package(Akonadi 1.12.0 QUIET CONFIG) set_package_properties(Akonadi PROPERTIES DESCRIPTION "Akonadi server libraries" URL "http://pim.kde.org/akonadi" TYPE REQUIRED PURPOSE "Akonadi is required to build KDEPIM") find_package(ZLIB) @@ -178,7 +178,7 @@ find_package(Grantlee 0.3.0 QUIET CONFIG) set_package_properties(Grantlee PROPERTIES DESCRIPTION "The Grantlee Template System" URL "http://www.gitorious.org/grantlee/pages/Home" TYPE REQUIRED PURPOSE "Grantlee is requires for kmail and templating, theming for KJots, KaddressBook, KNotes and MessageViewer(KMail)." ) - find_package(Baloo 4.12.83 QUIET CONFIG) + find_package(Baloo 4.13.0 QUIET CONFIG) set_package_properties(Baloo PROPERTIES DESCRIPTION "The Baloo libraries" URL "http://www.kde.org" TYPE REQUIRED PURPOSE "Baloo provides search capabilities in KMail and Akonadi") # Xsltproc diff -Nru kdepim-4.12.97/contactthemeeditor/contactconfigurationdialog.cpp kdepim-4.13.0/contactthemeeditor/contactconfigurationdialog.cpp --- kdepim-4.12.97/contactthemeeditor/contactconfigurationdialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/contactthemeeditor/contactconfigurationdialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -17,6 +17,8 @@ #include "contactconfigurationdialog.h" #include "contacteditorutil.h" +#include "pimcommon/texteditor/richtexteditor/richtexteditorwidget.h" + #include "configurewidget.h" @@ -28,7 +30,6 @@ #include #include #include -#include #include #include @@ -58,7 +59,7 @@ tab->addTab(w, i18n("General")); - mDefaultTemplate = new KTextEdit; + mDefaultTemplate = new PimCommon::RichTextEditorWidget; mDefaultTemplate->setAcceptRichText(false); tab->addTab(mDefaultTemplate, i18n("Default Template")); diff -Nru kdepim-4.12.97/contactthemeeditor/contactconfigurationdialog.h kdepim-4.13.0/contactthemeeditor/contactconfigurationdialog.h --- kdepim-4.12.97/contactthemeeditor/contactconfigurationdialog.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/contactthemeeditor/contactconfigurationdialog.h 2014-04-10 07:40:20.000000000 +0000 @@ -28,7 +28,10 @@ class ContactEditor; } -class KTextEdit; + +namespace PimCommon { +class RichTextEditorWidget; +} class ContactConfigureDialog : public KDialog { Q_OBJECT @@ -45,7 +48,7 @@ private: GrantleeThemeEditor::ConfigureWidget *mConfigureWidget; - KTextEdit *mDefaultTemplate; + PimCommon::RichTextEditorWidget *mDefaultTemplate; Akonadi::ContactEditor *mDefaultContact; }; diff -Nru kdepim-4.12.97/contactthemeeditor/contacteditormainwindow.cpp kdepim-4.13.0/contactthemeeditor/contacteditormainwindow.cpp --- kdepim-4.12.97/contactthemeeditor/contacteditormainwindow.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/contactthemeeditor/contacteditormainwindow.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -46,6 +46,8 @@ { KGlobal::locale()->insertCatalog( QLatin1String("akonadicontact") ); KGlobal::locale()->insertCatalog( QLatin1String("kabc") ); + KGlobal::locale()->insertCatalog( QLatin1String("libpimcommon") ); + setupActions(); setupGUI(); updateActions(); @@ -173,24 +175,30 @@ bool ContactEditorMainWindow::slotSaveTheme() { bool result = false; - if (mContactEditor) + if (mContactEditor) { result = mContactEditor->saveTheme(false); + mSaveAction->setEnabled(result); + } return result; } void ContactEditorMainWindow::slotCloseTheme() { - saveCurrentProject(false); + saveCurrentProject(SaveAndCloseTheme); } void ContactEditorMainWindow::slotOpenTheme() { - if (!saveCurrentProject(false)) + if (!saveCurrentProject(SaveOnly)) return; const QString directory = KFileDialog::getExistingDirectory(KUrl( "kfiledialog:///OpenTheme" ), this, i18n("Select theme directory")); + if (directory.isEmpty()) + return; + closeThemeEditor(); loadTheme(directory); mRecentFileAction->addUrl(KUrl(directory)); + mSaveAction->setEnabled(false); } void ContactEditorMainWindow::loadTheme(const QString &directory) @@ -219,13 +227,28 @@ mContactEditor->addExtraPage(); } -bool ContactEditorMainWindow::saveCurrentProject(bool createNewTheme) +void ContactEditorMainWindow::closeThemeEditor() +{ + delete mContactEditor; + mContactEditor = 0; + setCentralWidget(0); + updateActions(); +} + +bool ContactEditorMainWindow::saveCurrentProject(ActionSaveTheme act) { if (mContactEditor) { if (!mContactEditor->saveTheme()) return false; } - if (createNewTheme) { + switch(act) { + case SaveOnly: + break; + case SaveAndCloseTheme: { + closeThemeEditor(); + break; + } + case SaveAndCreateNewTheme: { delete mContactEditor; mContactEditor = 0; QPointer dialog = new GrantleeThemeEditor::NewThemeDialog(this); @@ -246,23 +269,20 @@ } delete dialog; updateActions(); - } else { - delete mContactEditor; - mContactEditor = 0; - setCentralWidget(0); - updateActions(); + break; + } } return true; } void ContactEditorMainWindow::slotNewTheme() { - saveCurrentProject(true); + saveCurrentProject(SaveAndCreateNewTheme); } void ContactEditorMainWindow::closeEvent(QCloseEvent *e) { - if (!saveCurrentProject(false)) + if (!saveCurrentProject(SaveAndCloseTheme)) e->ignore(); else e->accept(); @@ -270,7 +290,7 @@ void ContactEditorMainWindow::slotQuitApp() { - if (saveCurrentProject(false)) + if (saveCurrentProject(SaveAndCloseTheme)) kapp->quit(); } @@ -289,9 +309,10 @@ void ContactEditorMainWindow::slotThemeSelected(const KUrl &url) { - if (!saveCurrentProject(false)) + if (!saveCurrentProject(SaveAndCloseTheme)) return; loadTheme(url.path()); + mSaveAction->setEnabled(false); } void ContactEditorMainWindow::slotSaveAsTheme() diff -Nru kdepim-4.12.97/contactthemeeditor/contacteditormainwindow.h kdepim-4.13.0/contactthemeeditor/contacteditormainwindow.h --- kdepim-4.12.97/contactthemeeditor/contacteditormainwindow.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/contactthemeeditor/contacteditormainwindow.h 2014-04-10 07:40:20.000000000 +0000 @@ -53,11 +53,18 @@ void slotSaveAsTheme(); private: + enum ActionSaveTheme { + SaveOnly = 0, + SaveAndCloseTheme, + SaveAndCreateNewTheme + }; + void loadTheme(const QString &directory); void readConfig(); void updateActions(); - bool saveCurrentProject(bool createNewTheme); + bool saveCurrentProject(ActionSaveTheme act); void setupActions(); + void closeThemeEditor(); ContactEditorPage *mContactEditor; KAction *mNewThemeAction; KAction *mCloseThemeAction; diff -Nru kdepim-4.12.97/contactthemeeditor/contacteditorpage.cpp kdepim-4.13.0/contactthemeeditor/contacteditorpage.cpp --- kdepim-4.12.97/contactthemeeditor/contacteditorpage.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/contactthemeeditor/contacteditorpage.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -223,7 +223,7 @@ { QString filename = KInputDialog::getText(i18n("Filename of extra page"), i18n("Filename:")); if (!filename.isEmpty()) { - if (!filename.endsWith(QLatin1String(".html"))) { + if (!filename.endsWith(QLatin1String(".html")) && !filename.endsWith(QLatin1String(".css")) && !filename.endsWith(QLatin1String(".js"))) { filename += QLatin1String(".html"); } createExtraPage(filename); diff -Nru kdepim-4.12.97/debian/changelog kdepim-4.13.0/debian/changelog --- kdepim-4.12.97/debian/changelog 2014-04-02 09:20:10.000000000 +0000 +++ kdepim-4.13.0/debian/changelog 2014-04-10 20:52:58.000000000 +0000 @@ -1,3 +1,13 @@ +kdepim (4:4.13.0-0ubuntu1) trusty; urgency=medium + + [ Jonathan Riddell ] + * New upstream KDE Software Compilation release + + [ Harald Sitter ] + * Remove ubuntuone icons + + -- Jonathan Riddell Thu, 10 Apr 2014 21:52:55 +0100 + kdepim (4:4.12.97-0ubuntu1) trusty; urgency=medium * New upstream release candidate diff -Nru kdepim-4.12.97/debian/control kdepim-4.13.0/debian/control --- kdepim-4.12.97/debian/control 2014-04-02 09:20:10.000000000 +0000 +++ kdepim-4.13.0/debian/control 2014-04-10 20:52:58.000000000 +0000 @@ -9,7 +9,7 @@ George Kiagiadakis , Eshat Cakar Build-Depends: kde-sc-dev-latest (>= 4:4.10.2), cmake, debhelper (>= 7.3.16), pkg-kde-tools (>= 0.12), - kdepimlibs5-dev (>= 4:4.12.97), libphonon-dev (>= 4:4.6.0really4.3.80), + kdepimlibs5-dev (>= 4:4.13.0), libphonon-dev (>= 4:4.6.0really4.3.80), pkg-config, libgpgme11-dev, libboost1.54-dev (>= 1.40.0-2), libboost-graph1.54-dev (>= 1.40.0-2), libsasl2-dev, xsltproc, libxss-dev, libqca2-dev (>= 2.0.0), libassuan-dev, @@ -18,7 +18,7 @@ libakonadi-dev (>= 1.7.2), shared-desktop-ontologies (>= 0.6.50), libgrantlee-dev, libqtwebkit-dev, libqt4-opengl-dev, libprison-dev, libindicate-qt-dev, libxml2-dev, sharutils, - libkactivities-dev (>= 4:4.12.97), liblink-grammar4-dev, libqjson-dev, baloo-dev (>= 4:4.12.97), + libkactivities-dev (>= 4:4.13.0), liblink-grammar4-dev, libqjson-dev, baloo-dev (>= 4:4.13.0), libkgapi-dev (>= 2.1.0) Build-Depends-Indep: dblatex Standards-Version: 3.9.3 @@ -71,7 +71,7 @@ kontact (>= ${binary:Version}), korganizer (>= ${binary:Version}), ktimetracker (>= ${binary:Version}), kde-config-pimactivity (>= ${binary:Version}), libkdepim4 (= ${binary:Version}), libpimcommon4 (= ${binary:Version}), - kdepimlibs5-dev (>= 4:4.12.97), libphonon-dev (>= 4:4.6.0really4.3.80), + kdepimlibs5-dev (>= 4:4.13.0), libphonon-dev (>= 4:4.6.0really4.3.80), libgpgme11-dev, libboost1.54-dev, libboost-graph1.54-dev, libsasl2-dev, libxss-dev, libqca2-dev (>= 2.0.0), libpisock-dev, libassuan-dev, libstreams-dev, libstreamanalyzer-dev, libsearchclient-dev, libstrigihtmlgui-dev, diff -Nru kdepim-4.12.97/debian/storageservicemanager.install kdepim-4.13.0/debian/storageservicemanager.install --- kdepim-4.12.97/debian/storageservicemanager.install 2014-04-02 09:20:10.000000000 +0000 +++ kdepim-4.13.0/debian/storageservicemanager.install 2014-04-10 20:52:58.000000000 +0000 @@ -2,16 +2,11 @@ usr/share/applications/kde4/storageservicemanager.desktop usr/share/icons/hicolor/16x16/apps/kdepim-dropbox.png usr/share/icons/hicolor/16x16/apps/kdepim-googledrive.png -usr/share/icons/hicolor/16x16/apps/kdepim-ubuntuone.png usr/share/icons/hicolor/22x22/apps/kdepim-dropbox.png usr/share/icons/hicolor/22x22/apps/kdepim-googledrive.png -usr/share/icons/hicolor/24x24/apps/kdepim-ubuntuone.png usr/share/icons/hicolor/32x32/apps/kdepim-dropbox.png usr/share/icons/hicolor/32x32/apps/kdepim-googledrive.png -usr/share/icons/hicolor/32x32/apps/kdepim-ubuntuone.png usr/share/icons/hicolor/48x48/apps/kdepim-dropbox.png usr/share/icons/hicolor/48x48/apps/kdepim-googledrive.png -usr/share/icons/hicolor/48x48/apps/kdepim-ubuntuone.png -usr/share/icons/hicolor/64x64/apps/ubuntuone.png usr/share/kde4/apps/storageservicemanager/storageservicemanager.notifyrc usr/share/kde4/apps/storageservicemanager/storageservicemanagerui.rc diff -Nru kdepim-4.12.97/grantleethemeeditor/desktopfilepage.cpp kdepim-4.13.0/grantleethemeeditor/desktopfilepage.cpp --- kdepim-4.12.97/grantleethemeeditor/desktopfilepage.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/grantleethemeeditor/desktopfilepage.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -111,6 +111,9 @@ mAuthor->setText(GrantleeThemeEditor::GrantleeThemeEditorSettings::author()); connect(mDescription->editor(), SIGNAL(textChanged()), this, SIGNAL(changed())); + connect(mEmail, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); + connect(mAuthor, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); + connect(mVersion, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); } DesktopFilePage::~DesktopFilePage() diff -Nru kdepim-4.12.97/headerthemeeditor/defaultcompletion.cpp kdepim-4.13.0/headerthemeeditor/defaultcompletion.cpp --- kdepim-4.12.97/headerthemeeditor/defaultcompletion.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/headerthemeeditor/defaultcompletion.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -23,6 +23,7 @@ QStringList lst; lst <" ) <" +header.abasoluteThemePath defines path where is installed themes. KMail doesn't load relative path + + +We have some variable which can use to define theme: +- i18n variables: (default translated string) + header.subjecti18n + header.replyToi18n + header.toi18n + header.cci18n + header.bcci18n + header.fromi18n + header.spamstatusi18n + header.datei18n + header.resentfromi18n + header.vcardi18n + header.resenttoi18n + +- theme variables: + header.absoluteThemePath + header.subject + header.replyTo + header.replyToStr + header.to + header.toStr + header.cc + header.ccStr + header.bcc + header.bccStr + header.from + header.fromStr + header.spamHTML + header.dateshort + header.date + header.useragent + header.xmailer + header.resentfrom + header.organization + header.vcardname + header.activecolordark + header.fontcolor + header.linkcolor + header.photowidth + header.photoheight + header.applicationDir + header.subjectDir + header.photourl + header.isprinting + header.resentto diff -Nru kdepim-4.12.97/headerthemeeditor/themeconfiguredialog.cpp kdepim-4.13.0/headerthemeeditor/themeconfiguredialog.cpp --- kdepim-4.12.97/headerthemeeditor/themeconfiguredialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/headerthemeeditor/themeconfiguredialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -17,6 +17,8 @@ #include "themeconfiguredialog.h" #include "themeeditorutil.h" +#include "pimcommon/texteditor/richtexteditor/richtexteditorwidget.h" +#include "pimcommon/texteditor/richtexteditor/richtexteditor.h" #include "configurewidget.h" @@ -50,12 +52,12 @@ QLabel *lab = new QLabel(i18n("Default email:")); lay->addWidget(lab); - mDefaultEmail = new KTextEdit; + mDefaultEmail = new PimCommon::RichTextEditorWidget; mDefaultEmail->setAcceptRichText(false); lay->addWidget(mDefaultEmail); tab->addTab(w, i18n("General")); - mDefaultTemplate = new KTextEdit; + mDefaultTemplate = new PimCommon::RichTextEditorWidget; mDefaultTemplate->setAcceptRichText(false); tab->addTab(mDefaultTemplate, i18n("Default Template")); @@ -77,7 +79,7 @@ { mConfigureWidget->setDefault(); mDefaultEmail->setPlainText(themeeditorutil::defaultMail()); - mDefaultTemplate->clear(); + mDefaultTemplate->editor()->clear(); } void ThemeConfigureDialog::slotOkClicked() diff -Nru kdepim-4.12.97/headerthemeeditor/themeconfiguredialog.h kdepim-4.13.0/headerthemeeditor/themeconfiguredialog.h --- kdepim-4.12.97/headerthemeeditor/themeconfiguredialog.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/headerthemeeditor/themeconfiguredialog.h 2014-04-10 07:40:20.000000000 +0000 @@ -21,6 +21,9 @@ #include class KTextEdit; +namespace PimCommon { +class RichTextEditorWidget; +} namespace GrantleeThemeEditor { class ConfigureWidget; } @@ -41,8 +44,8 @@ private: GrantleeThemeEditor::ConfigureWidget *mConfigureWidget; - KTextEdit *mDefaultTemplate; - KTextEdit *mDefaultEmail; + PimCommon::RichTextEditorWidget *mDefaultTemplate; + PimCommon::RichTextEditorWidget *mDefaultEmail; }; #endif // THEMECONFIGUREDIALOG_H diff -Nru kdepim-4.12.97/headerthemeeditor/themeeditormainwindow.cpp kdepim-4.13.0/headerthemeeditor/themeeditormainwindow.cpp --- kdepim-4.12.97/headerthemeeditor/themeeditormainwindow.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/headerthemeeditor/themeeditormainwindow.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -195,24 +195,31 @@ bool ThemeEditorMainWindow::slotSaveTheme() { bool result = false; - if (mThemeEditor) + if (mThemeEditor) { result = mThemeEditor->saveTheme(false); + mSaveAction->setEnabled(!result); + } return result; } void ThemeEditorMainWindow::slotCloseTheme() { - saveCurrentProject(false); + saveCurrentProject(SaveAndCloseTheme); } void ThemeEditorMainWindow::slotOpenTheme() { - if (!saveCurrentProject(false)) + if (!saveCurrentProject(SaveOnly)) return; const QString directory = KFileDialog::getExistingDirectory(KUrl( "kfiledialog:///OpenTheme" ), this, i18n("Select theme directory")); + if (directory.isEmpty()) { + return; + } + closeThemeEditor(); loadTheme(directory); mRecentFileAction->addUrl(KUrl(directory)); + mSaveAction->setEnabled(false); } void ThemeEditorMainWindow::loadTheme(const QString &directory) @@ -240,13 +247,29 @@ mThemeEditor->addExtraPage(); } -bool ThemeEditorMainWindow::saveCurrentProject(bool createNewTheme) +void ThemeEditorMainWindow::closeThemeEditor() +{ + delete mThemeEditor; + mThemeEditor = 0; + setCentralWidget(0); + updateActions(); +} + +bool ThemeEditorMainWindow::saveCurrentProject(ActionSaveTheme act) { if (mThemeEditor) { - if (!mThemeEditor->saveTheme()) + if (!mThemeEditor->saveTheme()) { return false; + } + } + switch(act) { + case SaveOnly: + break; + case SaveAndCloseTheme: { + closeThemeEditor(); + break; } - if (createNewTheme) { + case SaveAndCreateNewTheme: { delete mThemeEditor; mThemeEditor = 0; QPointer dialog = new GrantleeThemeEditor::NewThemeDialog(this); @@ -267,23 +290,21 @@ } delete dialog; updateActions(); - } else { - delete mThemeEditor; - mThemeEditor = 0; - setCentralWidget(0); - updateActions(); + break; + } } + return true; } void ThemeEditorMainWindow::slotNewTheme() { - saveCurrentProject(true); + saveCurrentProject(SaveAndCreateNewTheme); } void ThemeEditorMainWindow::closeEvent(QCloseEvent *e) { - if (!saveCurrentProject(false)) + if (!saveCurrentProject(SaveAndCloseTheme)) e->ignore(); else e->accept(); @@ -291,7 +312,7 @@ void ThemeEditorMainWindow::slotQuitApp() { - if (saveCurrentProject(false)) + if (saveCurrentProject(SaveAndCloseTheme)) kapp->quit(); } @@ -310,9 +331,10 @@ void ThemeEditorMainWindow::slotThemeSelected(const KUrl &url) { - if (!saveCurrentProject(false)) + if (!saveCurrentProject(SaveAndCloseTheme)) return; loadTheme(url.path()); + mSaveAction->setEnabled(false); } void ThemeEditorMainWindow::slotSaveAsTheme() diff -Nru kdepim-4.12.97/headerthemeeditor/themeeditormainwindow.h kdepim-4.13.0/headerthemeeditor/themeeditormainwindow.h --- kdepim-4.12.97/headerthemeeditor/themeeditormainwindow.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/headerthemeeditor/themeeditormainwindow.h 2014-04-10 07:40:20.000000000 +0000 @@ -56,11 +56,18 @@ void slotSaveAsTheme(); private: + enum ActionSaveTheme { + SaveOnly = 0, + SaveAndCloseTheme, + SaveAndCreateNewTheme + }; + void loadTheme(const QString &directory); void readConfig(); void updateActions(); - bool saveCurrentProject(bool createNewTheme); + bool saveCurrentProject(ActionSaveTheme act); void setupActions(); + void closeThemeEditor(); ThemeEditorPage *mThemeEditor; KAction *mNewThemeAction; KAction *mCloseThemeAction; diff -Nru kdepim-4.12.97/headerthemeeditor/themeeditorpage.cpp kdepim-4.13.0/headerthemeeditor/themeeditorpage.cpp --- kdepim-4.12.97/headerthemeeditor/themeeditorpage.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/headerthemeeditor/themeeditorpage.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -169,8 +169,8 @@ } } const QString newPath = themePath + QDir::separator() + mDesktopPage->themeName(); + mEditorPage->setPageFileName(mDesktopPage->filename()); mEditorPage->installTheme(newPath); - Q_FOREACH (EditorPage *page, mExtraPage) { page->installTheme(newPath); } @@ -232,7 +232,7 @@ { QString filename = KInputDialog::getText(i18n("Filename of extra page"), i18n("Filename:")); if (!filename.isEmpty()) { - if (!filename.endsWith(QLatin1String(".html"))) { + if (!filename.endsWith(QLatin1String(".html")) && !filename.endsWith(QLatin1String(".css")) && !filename.endsWith(QLatin1String(".js"))) { filename += QLatin1String(".html"); } createExtraPage(filename); diff -Nru kdepim-4.12.97/incidenceeditor-ng/incidenceattendee.cpp kdepim-4.13.0/incidenceeditor-ng/incidenceattendee.cpp --- kdepim-4.12.97/incidenceeditor-ng/incidenceattendee.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/incidenceeditor-ng/incidenceattendee.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -48,6 +48,26 @@ using namespace IncidenceEditorNG; +static bool compareAttendees(const KCalCore::Attendee::Ptr &newAttendee, + const KCalCore::Attendee::Ptr &originalAttendee) +{ + KCalCore::Attendee::Ptr originalClone(new KCalCore::Attendee(*originalAttendee)); + + if (newAttendee->name() != originalAttendee->name()) { + // What you put into an IncidenceEditorNG::AttendeeLine isn't exactly what you get out. + // In rare situations, such as "Doe\, John ", AttendeeLine will normalize + // the name, and set "Doe, John " instead. + // So, for isDirty() purposes, have that in mind, so we don't return that the editor is dirty + // when the user didn't edit anything. + QString dummy; + QString originalNameNormalized; + KPIMUtils::extractEmailAddressAndName(originalAttendee->fullName(), dummy, originalNameNormalized); + originalClone->setName(originalNameNormalized); + } + + return *newAttendee == *originalClone; +} + #ifdef KDEPIM_MOBILE_UI IncidenceAttendee::IncidenceAttendee( QWidget *parent, IncidenceDateTime *dateTime, Ui::EventOrTodoMore *ui ) @@ -236,7 +256,7 @@ foreach ( const KCalCore::Attendee::Ptr &attendee, originalList ) { bool found = false; for ( int i = 0; i < newList.size(); ++i ) { - if ( *newList.at( i )->attendee() == *attendee ) { + if ( compareAttendees( newList.at( i )->attendee(), attendee) ) { newList.removeAt( i ); found = true; break; diff -Nru kdepim-4.12.97/kaddressbook/kaddressbook-importer.desktop kdepim-4.13.0/kaddressbook/kaddressbook-importer.desktop --- kdepim-4.12.97/kaddressbook/kaddressbook-importer.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kaddressbook/kaddressbook-importer.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -20,6 +20,7 @@ Name[pl]=Plik importu Książki adresowej Name[pt]=Importação de ficheiros do KAddressbook Name[pt_BR]=Arquivo de importação do KAddressbook +Name[ru]=Импорт файла в адресную книгу Name[sk]=Importný súbor KAddressbook Name[sr]=К‑адресаров увоз фајла Name[sr@ijekavian]=К‑адресаров увоз фајла diff -Nru kdepim-4.12.97/kaddressbook/kaddressbookui.rc kdepim-4.13.0/kaddressbook/kaddressbookui.rc --- kdepim-4.12.97/kaddressbook/kaddressbookui.rc 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kaddressbook/kaddressbookui.rc 2014-04-10 07:40:20.000000000 +0000 @@ -1,5 +1,5 @@ - + &File @@ -88,6 +88,9 @@ + + + diff -Nru kdepim-4.12.97/kaddressbook/printing/grantlee/contactgrantleeprintaddressobject.cpp kdepim-4.13.0/kaddressbook/printing/grantlee/contactgrantleeprintaddressobject.cpp --- kdepim-4.12.97/kaddressbook/printing/grantlee/contactgrantleeprintaddressobject.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kaddressbook/printing/grantlee/contactgrantleeprintaddressobject.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -70,5 +70,5 @@ QString ContactGrantleePrintAddressObject::formattedAddress() const { - return mAddress.formattedAddress(); + return mAddress.formattedAddress().replace(QLatin1String("\n"), QLatin1String("
")); } diff -Nru kdepim-4.12.97/kaddressbook/printing/grantlee/contactgrantleeprintaddressobject.h kdepim-4.13.0/kaddressbook/printing/grantlee/contactgrantleeprintaddressobject.h --- kdepim-4.12.97/kaddressbook/printing/grantlee/contactgrantleeprintaddressobject.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kaddressbook/printing/grantlee/contactgrantleeprintaddressobject.h 2014-04-10 07:40:20.000000000 +0000 @@ -23,15 +23,15 @@ class ContactGrantleePrintAddressObject : public QObject { Q_OBJECT - Q_PROPERTY(QString name READ type) - Q_PROPERTY(QString name READ street) - Q_PROPERTY(QString name READ postOfficeBox) - Q_PROPERTY(QString name READ locality) - Q_PROPERTY(QString name READ region) - Q_PROPERTY(QString name READ postalCode) - Q_PROPERTY(QString name READ country) - Q_PROPERTY(QString name READ label) - Q_PROPERTY(QString name READ formattedAddress) + Q_PROPERTY(QString type READ type) + Q_PROPERTY(QString street READ street) + Q_PROPERTY(QString postOfficeBox READ postOfficeBox) + Q_PROPERTY(QString locality READ locality) + Q_PROPERTY(QString region READ region) + Q_PROPERTY(QString postalCode READ postalCode) + Q_PROPERTY(QString country READ country) + Q_PROPERTY(QString label READ label) + Q_PROPERTY(QString formattedAddress READ formattedAddress) public: explicit ContactGrantleePrintAddressObject(const KABC::Address &address, QObject *parent=0); diff -Nru kdepim-4.12.97/kaddressbook/printing/grantlee/contactgrantleeprintobject.cpp kdepim-4.13.0/kaddressbook/printing/grantlee/contactgrantleeprintobject.cpp --- kdepim-4.12.97/kaddressbook/printing/grantlee/contactgrantleeprintobject.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kaddressbook/printing/grantlee/contactgrantleeprintobject.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -29,12 +29,16 @@ #include +#include + + using namespace KABPrinting; ContactGrantleePrintObject::ContactGrantleePrintObject(const KABC::Addressee &address, QObject *parent) : QObject(parent), mAddress(address) { + Grantlee::registerSequentialContainer >(); Q_FOREACH ( const KABC::Address &addr, address.addresses() ) { mListAddress<formatDate( anniversary ) ); + } + return QString(); +} + +QString ContactGrantleePrintObject::profession() const +{ + return mAddress.custom( QLatin1String( "KADDRESSBOOK" ), + QLatin1String( "X-Profession" ) ); +} + +QString ContactGrantleePrintObject::office() const +{ + return mAddress.custom( QLatin1String( "KADDRESSBOOK" ), + QLatin1String( "X-Office" ) ); +} + +QString ContactGrantleePrintObject::manager() const +{ + return mAddress.custom( QLatin1String( "KADDRESSBOOK" ), + QLatin1String( "X-ManagersName" ) ); +} + +QString ContactGrantleePrintObject::assistant() const +{ + return mAddress.custom( QLatin1String( "KADDRESSBOOK" ), + QLatin1String( "X-AssistantsName" ) ); +} + +QString ContactGrantleePrintObject::spouse() const +{ + return mAddress.custom( QLatin1String( "KADDRESSBOOK" ), + QLatin1String( "X-SpousesName" ) ); +} diff -Nru kdepim-4.12.97/kaddressbook/printing/grantlee/contactgrantleeprintobject.h kdepim-4.13.0/kaddressbook/printing/grantlee/contactgrantleeprintobject.h --- kdepim-4.12.97/kaddressbook/printing/grantlee/contactgrantleeprintobject.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kaddressbook/printing/grantlee/contactgrantleeprintobject.h 2014-04-10 07:40:20.000000000 +0000 @@ -29,14 +29,15 @@ class ContactGrantleePrintObject : public QObject { Q_OBJECT - Q_PROPERTY(QString name READ realName) - Q_PROPERTY(QString name READ formattedName) - Q_PROPERTY(QString name READ prefix) - Q_PROPERTY(QString name READ givenName) - Q_PROPERTY(QString name READ additionalName) - Q_PROPERTY(QString name READ familyName) - Q_PROPERTY(QString name READ suffix) - Q_PROPERTY(QString name READ nickName) + Q_PROPERTY(QString name READ name) + Q_PROPERTY(QString realName READ realName) + Q_PROPERTY(QString formattedName READ formattedName) + Q_PROPERTY(QString prefix READ prefix) + Q_PROPERTY(QString givenName READ givenName) + Q_PROPERTY(QString additionalName READ additionalName) + Q_PROPERTY(QString familyName READ familyName) + Q_PROPERTY(QString suffix READ suffix) + Q_PROPERTY(QString nickName READ nickName) Q_PROPERTY(QStringList emails READ emails) Q_PROPERTY(QString organization READ organization) Q_PROPERTY(QString note READ note) @@ -52,11 +53,19 @@ Q_PROPERTY(QString addressBookName READ addressBookName) Q_PROPERTY(QString photo READ photo) Q_PROPERTY(QString logo READ logo) + Q_PROPERTY(QString anniversary READ anniversary) + Q_PROPERTY(QString profession READ profession) + Q_PROPERTY(QString office READ office) + Q_PROPERTY(QString manager READ manager) + Q_PROPERTY(QString assistant READ assistant) + Q_PROPERTY(QString spouse READ spouse) + //Add more functions public: explicit ContactGrantleePrintObject(const KABC::Addressee &address, QObject *parent=0); ~ContactGrantleePrintObject(); + QString name() const; QString realName() const; QString formattedName() const; QString prefix() const; @@ -81,18 +90,27 @@ QVariant geo() const; QString photo() const; QString logo() const; + QString anniversary() const; + QString profession() const; + QString office() const; + QString manager() const; + QString assistant() const; + QString spouse() const; + private: QString imgToDataUrl( const QImage &image ) const; - QList mListAddress; - QList mListPhones; - QList mListIm; + QList mListAddress; + QList mListPhones; + QList mListIm; ContactGrantleePrintGeoObject *mGeoObject; KABC::Addressee mAddress; }; } -Q_DECLARE_METATYPE(QList) -Q_DECLARE_METATYPE(QList) -Q_DECLARE_METATYPE(QList) -Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(KABPrinting::ContactGrantleePrintObject*) +Q_DECLARE_METATYPE(KABPrinting::ContactGrantleePrintAddressObject*) +Q_DECLARE_METATYPE(KABPrinting::ContactGrantleePrintPhoneObject*) +Q_DECLARE_METATYPE(KABPrinting::ContactGrantleePrintImObject*) Q_DECLARE_METATYPE(KABPrinting::ContactGrantleePrintGeoObject*) +Q_DECLARE_METATYPE(QList) + #endif // CONTACTGRANTLEEPRINTOBJECT_H diff -Nru kdepim-4.12.97/kaddressbook/printing/grantlee/README.themes kdepim-4.13.0/kaddressbook/printing/grantlee/README.themes --- kdepim-4.12.97/kaddressbook/printing/grantlee/README.themes 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kaddressbook/printing/grantlee/README.themes 2014-04-10 07:40:20.000000000 +0000 @@ -21,9 +21,27 @@ +Default i18n variable: + "birthdayi18n" => i18n( "Birthday" ); + "anniversaryi18n" => i18n( "Anniversary" ); + "emailsi18n" => i18n( "Emails" ); + "websitei18n" => i18n("Website"); + "blogUrli18n" => i18n( "Blog Feed" ); + "addressBookNamei18n" => i18n( "Address Book" ); + "notei18n" => i18n( "Note" ); + "departmenti18n" => i18n( "Department" ); + "Professioni18n" => i18n( "Profession" ); + "officei18n" => i18n( "Office" ); + "manageri18n" => i18n( "Manager's Name" ); + "assistanti18n" => i18n( "Assistant's Name" ); + "spousei18n" => i18n( "Partner's Name" ); + "imAddressi18n" => i18n( "IM Address" ); + + => All contact is stored in contacts object => We use a loop for as in example. We can use as variable: -- realName (QString) +- name (QString) + realName (QString) formattedName (QString) prefix (QString) givenName (QString) @@ -47,6 +65,13 @@ addressBookName (QString) photo (QString) logo (QString) + anniversary (QString) + profession (QString) + office (QString) + manager (QString) + assistant (QString) + spouse (QString) + Element for address: - type (QString) diff -Nru kdepim-4.12.97/kaddressbook/printing/grantlee/themes/big-theme-example/theme.desktop kdepim-4.13.0/kaddressbook/printing/grantlee/themes/big-theme-example/theme.desktop --- kdepim-4.12.97/kaddressbook/printing/grantlee/themes/big-theme-example/theme.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kaddressbook/printing/grantlee/themes/big-theme-example/theme.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -20,6 +20,7 @@ Name[pl]=Przykładowy duży tytuł Name[pt]=Título grande de exemplo Name[pt_BR]=Exemplo de título grande +Name[ru]=Пример оформления с крупными заголовками Name[sk]=Ukážkový veľký titulok Name[sr]=Пример великог наслова Name[sr@ijekavian]=Пример великог наслова @@ -51,6 +52,7 @@ Description[pl]=Przykładowy duży tytuł motywu drukowania grantlee Description[pt]=Tema de impressão de exemplo do Grantlee com um título grande Description[pt_BR]=Exemplo de tema de impressão de título grande do Grantlee +Description[ru]=Пример оформления для печати с крупными заголовками Description[sk]=Ukážková veľká tlačová téma grantlee Description[sr]=Пример великог наслова, Грантлијева тема за штампање Description[sr@ijekavian]=Пример великог наслова, Грантлијева тема за штампање diff -Nru kdepim-4.12.97/kaddressbook/printing/grantlee/themes/default/theme.desktop kdepim-4.13.0/kaddressbook/printing/grantlee/themes/default/theme.desktop --- kdepim-4.12.97/kaddressbook/printing/grantlee/themes/default/theme.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kaddressbook/printing/grantlee/themes/default/theme.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -87,6 +87,7 @@ Description[pl]=Domyślny motyw drukowania grantlee Description[pt]=Tema de impressão predefinido do Grantlee Description[pt_BR]=Tema de impressão padrão do Grantlee +Description[ru]=Оформление по умолчанию для печати Description[sk]=Predvolená tlačová téma grantlee Description[sr]=Подразумевана Грантлијева тема за штампање Description[sr@ijekavian]=Подразумевана Грантлијева тема за штампање diff -Nru kdepim-4.12.97/kaddressbook/viewertemplates/theme.desktop kdepim-4.13.0/kaddressbook/viewertemplates/theme.desktop --- kdepim-4.12.97/kaddressbook/viewertemplates/theme.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kaddressbook/viewertemplates/theme.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -84,7 +84,7 @@ Description[nb]=Standardtema for kaddressbok. Description[nds]=KAddressbook-Standardmuster Description[nl]=Thema van KaddressBook. -Description[pl]=Domyślny motyw książki adresowej +Description[pl]=Domyślny wystrój książki adresowej Description[pt]=O tema predefinido do KAddressbook. Description[pt_BR]=Tema padrão do KAddressBook Description[ru]=Оформление адресной книги по умолчанию. diff -Nru kdepim-4.12.97/kleopatra/commands/dumpcrlcachecommand.cpp kdepim-4.13.0/kleopatra/commands/dumpcrlcachecommand.cpp --- kdepim-4.12.97/kleopatra/commands/dumpcrlcachecommand.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kleopatra/commands/dumpcrlcachecommand.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -61,7 +62,11 @@ explicit DumpCrlCacheDialog( QWidget * parent=0 ) : QDialog( parent ), ui( this ) { - + readConfig(); + } + ~DumpCrlCacheDialog() + { + writeConfig(); } Q_SIGNALS: @@ -76,6 +81,22 @@ } private: + void readConfig() + { + KConfigGroup dialog( KGlobal::config(), "DumpCrlCacheDialog" ); + const QSize size = dialog.readEntry( "Size", QSize(600, 400) ); + if ( size.isValid() ) { + resize( size ); + } + } + + void writeConfig() + { + KConfigGroup dialog( KGlobal::config(), "DumpCrlCacheDialog" ); + dialog.writeEntry( "Size", size() ); + dialog.sync(); + } + struct Ui { KDLogTextWidget logTextWidget; KPushButton updateButton, closeButton; diff -Nru kdepim-4.12.97/kleopatra/conf/kleopatra_config_appear.desktop kdepim-4.13.0/kleopatra/conf/kleopatra_config_appear.desktop --- kdepim-4.12.97/kleopatra/conf/kleopatra_config_appear.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kleopatra/conf/kleopatra_config_appear.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -105,7 +105,7 @@ Comment[et]=Värvide ja fontide seadistamine Comment[eu]=Kolore eta letra-tipoen konfigurazioa Comment[fa]=پیکربندی رنگها و قلمها -Comment[fi]=Värien ja kirjasinten asetukset +Comment[fi]=Värien ja fonttien asetukset Comment[fr]=Configuration des polices et des couleurs Comment[fy]=Kleur- en lettertype-ynstellings Comment[ga]=Cumraíocht na nDathanna/gClónna diff -Nru kdepim-4.12.97/kleopatra/dialogs/certificatedetailsdialog.cpp kdepim-4.13.0/kleopatra/dialogs/certificatedetailsdialog.cpp --- kdepim-4.12.97/kleopatra/dialogs/certificatedetailsdialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kleopatra/dialogs/certificatedetailsdialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -128,6 +128,22 @@ q, SLOT(slotKeysMayHaveChanged()) ); } + void readConfig() + { + KConfigGroup dialog( KGlobal::config(), "CertificateDetailsDialog" ); + const QSize size = dialog.readEntry( "Size", QSize(600, 400) ); + if ( size.isValid() ) { + q->resize( size ); + } + } + + void writeConfig() + { + KConfigGroup dialog( KGlobal::config(), "CertificateDetailsDialog" ); + dialog.writeEntry( "Size", q->size() ); + dialog.sync(); + } + private: void startCommandImplementation( const QPointer & ptr, const char * slot ) { connect( ptr, SIGNAL(finished()), q, slot ); @@ -442,10 +458,13 @@ CertificateDetailsDialog::CertificateDetailsDialog( QWidget * p, Qt::WindowFlags f ) : KDialog( p, f ), d( new Private( this ) ) { - + d->readConfig(); } -CertificateDetailsDialog::~CertificateDetailsDialog() {} +CertificateDetailsDialog::~CertificateDetailsDialog() +{ + d->writeConfig(); +} void CertificateDetailsDialog::setKey( const Key & key ) { diff -Nru kdepim-4.12.97/kleopatra/dialogs/deletecertificatesdialog.cpp kdepim-4.13.0/kleopatra/dialogs/deletecertificatesdialog.cpp --- kdepim-4.12.97/kleopatra/dialogs/deletecertificatesdialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kleopatra/dialogs/deletecertificatesdialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include @@ -81,6 +83,22 @@ QWhatsThis::showText( QCursor::pos(), widget->whatsThis() ); } + void readConfig() + { + KConfigGroup dialog( KGlobal::config(), "DeleteCertificatesDialog" ); + const QSize size = dialog.readEntry( "Size", QSize(600, 400) ); + if ( size.isValid() ) { + q->resize( size ); + } + } + + void writeConfig() + { + KConfigGroup dialog( KGlobal::config(), "DeleteCertificatesDialog" ); + dialog.writeEntry( "Size", q->size() ); + dialog.sync(); + } + private: struct UI { QLabel selectedLB; @@ -147,10 +165,13 @@ DeleteCertificatesDialog::DeleteCertificatesDialog( QWidget * p, Qt::WindowFlags f ) : QDialog( p, f ), d( new Private( this ) ) { - + d->readConfig(); } -DeleteCertificatesDialog::~DeleteCertificatesDialog() {} +DeleteCertificatesDialog::~DeleteCertificatesDialog() +{ + d->writeConfig(); +} void DeleteCertificatesDialog::setSelectedKeys( const std::vector & keys ) { diff -Nru kdepim-4.12.97/kleopatra/dialogs/lookupcertificatesdialog.cpp kdepim-4.13.0/kleopatra/dialogs/lookupcertificatesdialog.cpp --- kdepim-4.12.97/kleopatra/dialogs/lookupcertificatesdialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kleopatra/dialogs/lookupcertificatesdialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -86,6 +86,8 @@ emit q->saveAsRequested( q->selectedCertificates() ); } + void readConfig(); + void writeConfig(); void enableDisableWidgets(); QString searchText() const { return ui.findED->text().trimmed(); } @@ -151,13 +153,39 @@ LookupCertificatesDialog::Private::~Private() {} + +void LookupCertificatesDialog::Private::readConfig() +{ + KConfigGroup dialog( KGlobal::config(), "LookupCertificatesDialog" ); + const QSize size = dialog.readEntry( "Size", QSize(600, 400) ); + if ( size.isValid() ) { + q->resize( size ); + } + const QByteArray headerState = dialog.readEntry( "header", QByteArray()); + if (!headerState.isEmpty()) + ui.resultTV->header()->restoreState(headerState); +} + +void LookupCertificatesDialog::Private::writeConfig() +{ + KConfigGroup dialog( KGlobal::config(), "LookupCertificatesDialog" ); + dialog.writeEntry( "header", ui.resultTV->header()->saveState()); + dialog.writeEntry( "Size", q->size() ); + dialog.sync(); +} + + LookupCertificatesDialog::LookupCertificatesDialog( QWidget * p, Qt::WindowFlags f ) : QDialog( p, f ), d( new Private( this ) ) { - + d->ui.findPB->setEnabled(false); + d->readConfig(); } -LookupCertificatesDialog::~LookupCertificatesDialog() {} +LookupCertificatesDialog::~LookupCertificatesDialog() +{ + d->writeConfig(); +} void LookupCertificatesDialog::setCertificates( const std::vector & certs ) { d->model->setKeys( certs ); diff -Nru kdepim-4.12.97/kleopatra/kleopatra.rc kdepim-4.13.0/kleopatra/kleopatra.rc --- kdepim-4.12.97/kleopatra/kleopatra.rc 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kleopatra/kleopatra.rc 2014-04-10 07:40:20.000000000 +0000 @@ -1,5 +1,5 @@ - + &File @@ -93,11 +93,6 @@ - - Search Toolbar - - - &Certificates diff -Nru kdepim-4.12.97/kleopatra/mainwindow_desktop.cpp kdepim-4.13.0/kleopatra/mainwindow_desktop.cpp --- kdepim-4.12.97/kleopatra/mainwindow_desktop.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kleopatra/mainwindow_desktop.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -79,6 +79,7 @@ #include #include #include +#include #include #include @@ -222,24 +223,36 @@ TabWidget tabWidget; - explicit UI( MainWindow * q ) - : tabWidget( q ) - { - KDAB_SET_OBJECT_NAME( tabWidget ); - - q->setCentralWidget(&tabWidget); - KPIM::ProgressDialog * progressDialog = new KPIM::ProgressDialog( q->statusBar(), q ); - KDAB_SET_OBJECT_NAME( progressDialog ); - progressDialog->hide(); - KPIM::StatusbarProgressWidget * statusBarProgressWidget - = new KPIM::StatusbarProgressWidget( progressDialog, q->statusBar() ); - KDAB_SET_OBJECT_NAME( statusBarProgressWidget ); - q->statusBar()->addPermanentWidget( statusBarProgressWidget, 0 ); - statusBarProgressWidget->show(); - } + explicit UI( MainWindow * q ); } ui; }; +MainWindow::Private::UI::UI(MainWindow *q) + : tabWidget( q ) +{ + KDAB_SET_OBJECT_NAME( tabWidget ); + + QWidget *mainWidget = new QWidget; + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(0); + mainWidget->setLayout(vbox); + SearchBar * const searchBar = new SearchBar; + vbox->addWidget(searchBar); + tabWidget.connectSearchBar( searchBar ); + vbox->addWidget(&tabWidget); + + q->setCentralWidget(mainWidget); + KPIM::ProgressDialog * progressDialog = new KPIM::ProgressDialog( q->statusBar(), q ); + KDAB_SET_OBJECT_NAME( progressDialog ); + progressDialog->hide(); + KPIM::StatusbarProgressWidget * statusBarProgressWidget + = new KPIM::StatusbarProgressWidget( progressDialog, q->statusBar() ); + KDAB_SET_OBJECT_NAME( statusBarProgressWidget ); + q->statusBar()->addPermanentWidget( statusBarProgressWidget, 0 ); + statusBarProgressWidget->show(); +} + + MainWindow::Private::Private( MainWindow * qq ) : q( qq ), controller( q ), @@ -289,14 +302,6 @@ KActionCollection * const coll = q->actionCollection(); - KAction * const searchBarAction = new KAction( q ); - SearchBar * const searchBar = new SearchBar( q ); - - ui.tabWidget.connectSearchBar( searchBar ); - - searchBarAction->setDefaultWidget( searchBar ); - coll->addAction( QLatin1String("key_search_bar"), searchBarAction ); - const action_data action_data[] = { // most have been MOVED TO keylistcontroller.cpp // Tools menu diff -Nru kdepim-4.12.97/kleopatra/view/tabwidget.cpp kdepim-4.13.0/kleopatra/view/tabwidget.cpp --- kdepim-4.12.97/kleopatra/view/tabwidget.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kleopatra/view/tabwidget.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -52,12 +52,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -386,28 +386,28 @@ const action_data actionDataNew = { "window_new_tab", i18n("New Tab"), i18n("Open a new tab"), - "tab-new-background", q, SLOT(slotNewTab()), i18n("CTRL+SHIFT+N"), false, true + "tab-new-background", q, SLOT(slotNewTab()), QLatin1String("CTRL+SHIFT+N"), false, true }; newAction = make_action_from_data( actionDataNew, q ); struct action_data actionData[NumPageActions] = { { "window_rename_tab", i18n("Rename Tab..."), i18n("Rename this tab"), - "edit-rename", q, SLOT(slotRenameCurrentTab()), i18n("CTRL+SHIFT+R"), false, false }, + "edit-rename", q, SLOT(slotRenameCurrentTab()), QLatin1String("CTRL+SHIFT+R"), false, false }, { "window_duplicate_tab", i18n("Duplicate Tab"), i18n("Duplicate this tab"), - "tab-duplicate", q, SLOT(slotDuplicateCurrentTab()), i18n("CTRL+SHIFT+D"), false, true }, + "tab-duplicate", q, SLOT(slotDuplicateCurrentTab()), QLatin1String("CTRL+SHIFT+D"), false, true }, { "window_close_tab", i18n("Close Tab"), i18n("Close this tab"), - "tab-close", q, SLOT(slotCloseCurrentTab()), i18n("CTRL+SHIFT+W"), false, false }, // ### CTRL-W when available + "tab-close", q, SLOT(slotCloseCurrentTab()), QLatin1String("CTRL+SHIFT+W"), false, false }, // ### CTRL-W when available { "window_move_tab_left", i18n("Move Tab Left"), QString(), - 0, q, SLOT(slotMoveCurrentTabLeft()), i18n("CTRL+SHIFT+LEFT"), false, false }, + 0, q, SLOT(slotMoveCurrentTabLeft()), QLatin1String("CTRL+SHIFT+LEFT"), false, false }, { "window_move_tab_right", i18n("Move Tab Right"), QString(), - 0, q, SLOT(slotMoveCurrentTabRight()), i18n("CTRL+SHIFT+RIGHT"), false, false }, + 0, q, SLOT(slotMoveCurrentTabRight()), QLatin1String("CTRL+SHIFT+RIGHT"), false, false }, { "window_view_hierarchical", i18n("Hierarchical Certificate List"), QString(), 0, q, SLOT(slotToggleHierarchicalView(bool)), QString(), true, false }, { "window_expand_all", i18n("Expand All"), QString(), - 0, q, SLOT(slotExpandAll()), i18n("CTRL+."), false, false }, + 0, q, SLOT(slotExpandAll()), QLatin1String("CTRL+."), false, false }, { "window_collapse_all", i18n("Collapse All"), QString(), - 0, q, SLOT(slotCollapseAll()), i18n("CTRL+,"), false, false }, + 0, q, SLOT(slotCollapseAll()), QLatin1String("CTRL+,"), false, false }, }; for ( unsigned int i = 0 ; i < NumPageActions ; ++i ) @@ -527,17 +527,15 @@ tabWidget.setCurrentIndex( tabWidget.count()-1 ); } -#ifndef QT_NO_INPUTDIALOG void TabWidget::Private::renamePage( Page * page ) { if ( !page ) return; - bool ok = false; - const QString text = QInputDialog::getText( q, i18n("Rename Tab"), i18n("New tab title:"), QLineEdit::Normal, page->title(), &ok ); + bool ok; + const QString text = KInputDialog::getText( i18n("Rename Tab"), i18n("New tab title:"), page->title(), &ok, q); if ( !ok ) return; page->setTitle( text ); } -#endif void TabWidget::Private::duplicatePage( Page * page ) { if ( !page ) diff -Nru kdepim-4.12.97/kleopatra/view/tabwidget.h kdepim-4.13.0/kleopatra/view/tabwidget.h --- kdepim-4.12.97/kleopatra/view/tabwidget.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kleopatra/view/tabwidget.h 2014-04-10 07:40:20.000000000 +0000 @@ -107,9 +107,7 @@ Q_PRIVATE_SLOT( d, void slotPageKeyFilterChanged( const boost::shared_ptr & ) ) Q_PRIVATE_SLOT( d, void slotPageStringFilterChanged( const QString & ) ) Q_PRIVATE_SLOT( d, void slotPageHierarchyChanged( bool ) ) -#ifndef QT_NO_INPUTDIALOG Q_PRIVATE_SLOT( d, void slotRenameCurrentTab() ) -#endif // QT_NO_INPUTDIALOG Q_PRIVATE_SLOT( d, void slotNewTab() ) Q_PRIVATE_SLOT( d, void slotDuplicateCurrentTab() ) Q_PRIVATE_SLOT( d, void slotCloseCurrentTab() ) diff -Nru kdepim-4.12.97/kmail/data/kmail_config_misc.desktop kdepim-4.13.0/kmail/data/kmail_config_misc.desktop --- kdepim-4.12.97/kmail/data/kmail_config_misc.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/data/kmail_config_misc.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -151,6 +151,7 @@ X-KDE-Keywords[bs]=kmail, razno X-KDE-Keywords[ca]=kmail,misc X-KDE-Keywords[ca@valencia]=kmail,misc +X-KDE-Keywords[cs]=kmail,různé X-KDE-Keywords[da]=kmail,diverse X-KDE-Keywords[de]=KMail,Verschiedenes X-KDE-Keywords[el]=kmail,διάφορα diff -Nru kdepim-4.12.97/kmail/data/kmail_view.desktop kdepim-4.13.0/kmail/data/kmail_view.desktop --- kdepim-4.12.97/kmail/data/kmail_view.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/data/kmail_view.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -34,7 +34,7 @@ Name[pt]=Janela do KMail Name[pt_BR]=Exibição do KMail Name[ro]=Vizualizare KMail -Name[ru]=Представление KMail +Name[ru]=Просмотр в KMail Name[sk]=Pohľad KMail Name[sl]=KMailov prikaz Name[sr]=Приказ К‑поште diff -Nru kdepim-4.12.97/kmail/editor/kmcomposewin.cpp kdepim-4.13.0/kmail/editor/kmcomposewin.cpp --- kdepim-4.12.97/kmail/editor/kmcomposewin.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/editor/kmcomposewin.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -3576,6 +3576,7 @@ void KMComposeWin::slotUploadFileFailed(const QString &serviceName, const QString &fileName) { Q_UNUSED(serviceName); + Q_UNUSED(fileName); KMessageBox::error(this, i18n("An error occurred while sending the file."), i18n("Upload file")); --mNumProgressUploadFile; } diff -Nru kdepim-4.12.97/kmail/identity/identitydialog.cpp kdepim-4.13.0/kmail/identity/identitydialog.cpp --- kdepim-4.12.97/kmail/identity/identitydialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/identity/identitydialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -197,7 +197,7 @@ KPIMUtils::EmailValidator* emailValidator = new KPIMUtils::EmailValidator( this ); mEmailEdit->setValidator( emailValidator ); - // "Email Aliases" stsring text edit and label: + // "Email Aliases" string text edit and label: ++row; mAliasEdit = new PimCommon::SimpleStringListEditor( tab ); glay->addWidget( mAliasEdit, row, 1 ); @@ -373,6 +373,7 @@ // "Reply-To Address" line edit and label: ++row; mReplyToEdit = new KPIM::AddresseeLineEdit( tab, true ); + mReplyToEdit->setClearButtonShown(true); mReplyToEdit->setObjectName( QLatin1String("mReplyToEdit") ); glay->addWidget( mReplyToEdit, row, 1 ); label = new QLabel ( i18n("&Reply-To address:"), tab ); @@ -396,6 +397,7 @@ // "CC addresses" line edit and label: ++row; mCcEdit = new KPIM::AddresseeLineEdit( tab, true ); + mCcEdit->setClearButtonShown(true); mCcEdit->setObjectName( QLatin1String("mCcEdit") ); glay->addWidget( mCcEdit, row, 1 ); label = new QLabel( i18n("&CC addresses:"), tab ); @@ -416,6 +418,7 @@ // "BCC addresses" line edit and label: ++row; mBccEdit = new KPIM::AddresseeLineEdit( tab, true ); + mBccEdit->setClearButtonShown(true); mBccEdit->setObjectName( QLatin1String("mBccEdit") ); glay->addWidget( mBccEdit, row, 1 ); label = new QLabel( i18n("&BCC addresses:"), tab ); @@ -651,7 +654,7 @@ // Validate email addresses const QString email = mEmailEdit->text().trimmed(); if ( !KPIMUtils::isValidSimpleAddress( email ) ) { - QString errorMsg( KPIMUtils::simpleEmailAddressErrorMsg() ); + const QString errorMsg( KPIMUtils::simpleEmailAddressErrorMsg() ); KMessageBox::sorry( this, errorMsg, i18n("Invalid Email Address") ); return; } diff -Nru kdepim-4.12.97/kmail/kmkernel.cpp kdepim-4.13.0/kmail/kmkernel.cpp --- kdepim-4.12.97/kmail/kmkernel.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/kmkernel.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -190,7 +190,6 @@ mFolderCollectionMonitor = new FolderCollectionMonitor( session, this ); - connect( mFolderCollectionMonitor->monitor(), SIGNAL(collectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)), SLOT(slotCollectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)) ); connect( mFolderCollectionMonitor->monitor(), SIGNAL(collectionRemoved(Akonadi::Collection)), SLOT(slotCollectionRemoved(Akonadi::Collection))); mEntityTreeModel = new Akonadi::EntityTreeModel( folderCollectionMonitor(), this ); @@ -1827,11 +1826,6 @@ TemplateParser::Util::deleteTemplate( QString::fromLatin1( "IDENTITY_%1" ).arg( identity ) ); } -void KMKernel::slotCollectionMoved( const Akonadi::Collection &collection, const Akonadi::Collection &source, const Akonadi::Collection &destination ) -{ - //TODO add undo/redo move collection -} - bool KMKernel::showPopupAfterDnD() { return GlobalSettings::self()->showPopupAfterDnD(); diff -Nru kdepim-4.12.97/kmail/kmkernel.h kdepim-4.13.0/kmail/kmkernel.h --- kdepim-4.12.97/kmail/kmkernel.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/kmkernel.h 2014-04-10 07:40:20.000000000 +0000 @@ -484,7 +484,6 @@ void slotProgressItemCompletedOrCanceled( KPIM::ProgressItem * item); void slotInstanceError(const Akonadi::AgentInstance& instance, const QString & message); void slotInstanceWarning(const Akonadi::AgentInstance&instance, const QString& message); - void slotCollectionMoved( const Akonadi::Collection &collection, const Akonadi::Collection &source, const Akonadi::Collection &destination ); void slotCollectionRemoved(const Akonadi::Collection& col); void slotDeleteIdentity( uint identity); void slotInstanceRemoved(const Akonadi::AgentInstance&); diff -Nru kdepim-4.12.97/kmail/kmmainwidget.cpp kdepim-4.13.0/kmail/kmmainwidget.cpp --- kdepim-4.12.97/kmail/kmmainwidget.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/kmmainwidget.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -4432,6 +4432,21 @@ return mVacationScriptIndicator; } +void KMMainWidget::updateVacationScriptStatus() +{ + updateVacationScriptStatus( mVacationIndicatorActive ); +} + +KMail::TagActionManager *KMMainWidget::tagActionManager() const +{ + return mTagActionManager; +} + +KMail::FolderShortcutActionManager *KMMainWidget::folderShortcutActionManager() const +{ + return mFolderShortcutActionManager; +} + void KMMainWidget::slotMessageSelected(const Akonadi::Item &item) { delete mShowBusySplashTimer; diff -Nru kdepim-4.12.97/kmail/kmmainwidget.h kdepim-4.13.0/kmail/kmmainwidget.h --- kdepim-4.12.97/kmail/kmmainwidget.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/kmmainwidget.h 2014-04-10 07:40:20.000000000 +0000 @@ -139,7 +139,7 @@ static const PtrList *mainWidgetList(); QWidget *vacationScriptIndicator() const; - void updateVacationScriptStatus() { updateVacationScriptStatus( mVacationIndicatorActive ); } + void updateVacationScriptStatus(); MailCommon::FolderTreeView *folderTreeView() const { return mFolderTreeWidget->folderTreeView(); @@ -148,13 +148,9 @@ /** Returns the XML GUI client. */ KXMLGUIClient* guiClient() const { return mGUIClient; } - KMail::TagActionManager *tagActionManager() const { - return mTagActionManager; - } + KMail::TagActionManager *tagActionManager() const; - KMail::FolderShortcutActionManager *folderShortcutActionManager() const { - return mFolderShortcutActionManager; - } + KMail::FolderShortcutActionManager *folderShortcutActionManager() const; void savePaneSelection(); void updatePaneTagComboBox(); diff -Nru kdepim-4.12.97/kmail/kmstartup.cpp kdepim-4.13.0/kmail/kmstartup.cpp --- kdepim-4.12.97/kmail/kmstartup.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/kmstartup.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -96,7 +96,8 @@ "akonadicontact", "kabc", "akonadi_sendlater_agent", - "akonadi_folderagent_agent" + "akonadi_folderagent_agent", + "libkgapi" }; KLocale * l = KGlobal::locale(); diff -Nru kdepim-4.12.97/kmail/messageactions.cpp kdepim-4.13.0/kmail/messageactions.cpp --- kdepim-4.12.97/kmail/messageactions.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/messageactions.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -55,7 +56,6 @@ #include #include #include -#include #include using namespace KMail; @@ -184,12 +184,8 @@ ac->addAction( QLatin1String("mailing_list"), mMailingListActionMenu ); mMailingListActionMenu->setEnabled(false); - mMonitor = new Akonadi::Monitor( this ); - //FIXME: Attachment fetching is not needed here, but on-demand loading is not supported ATM - mMonitor->itemFetchScope().fetchPayloadPart( Akonadi::MessagePart::Header ); - mMonitor->itemFetchScope().fetchAttribute(); - connect( mMonitor, SIGNAL(itemChanged(Akonadi::Item,QSet)), SLOT(slotItemModified(Akonadi::Item,QSet))); - connect( mMonitor, SIGNAL(itemRemoved(Akonadi::Item)), SLOT(slotItemRemoved(Akonadi::Item))); + connect( kmkernel->folderCollectionMonitor(), SIGNAL(itemChanged(Akonadi::Item,QSet)), SLOT(slotItemModified(Akonadi::Item,QSet))); + connect( kmkernel->folderCollectionMonitor(), SIGNAL(itemRemoved(Akonadi::Item)), SLOT(slotItemRemoved(Akonadi::Item))); mCustomTemplatesMenu = new TemplateParser::CustomTemplatesMenu( parent, ac ); @@ -222,20 +218,13 @@ void MessageActions::setCurrentMessage( const Akonadi::Item &msg, const Akonadi::Item::List &items ) { - mMonitor->setItemMonitored( mCurrentItem, false ); mCurrentItem = msg; if (!items.isEmpty()) { - Q_FOREACH( const Akonadi::Item& item, mVisibleItems ) { - mMonitor->setItemMonitored( item, false ); - } - if (!msg.isValid()) { - mVisibleItems.clear(); - } else { + if (msg.isValid()) { mVisibleItems = items; - Q_FOREACH( const Akonadi::Item& item, items ) { - mMonitor->setItemMonitored( item, true ); - } + } else { + mVisibleItems.clear(); } } @@ -244,7 +233,6 @@ clearMailingListActions(); } - mMonitor->setItemMonitored( mCurrentItem, true ); updateActions(); } diff -Nru kdepim-4.12.97/kmail/messageactions.h kdepim-4.13.0/kmail/messageactions.h --- kdepim-4.12.97/kmail/messageactions.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/messageactions.h 2014-04-10 07:40:20.000000000 +0000 @@ -35,12 +35,11 @@ class KMenu; namespace Akonadi { - class Item; - class Monitor; +class Item; } namespace TemplateParser { - class CustomTemplatesMenu; +class CustomTemplatesMenu; } namespace KMail { @@ -50,8 +49,8 @@ */ class MessageActions : public QObject { - Q_OBJECT - public: + Q_OBJECT +public: explicit MessageActions( KActionCollection* ac, QWidget *parent ); ~MessageActions(); void setMessageView( KMReaderWin *msgView ); @@ -92,18 +91,18 @@ void addWebShortcutsMenu( KMenu *menu, const QString & text ); - signals: +signals: // This signal is emitted when a reply is triggered and the // action has finished. // This is useful for the stand-alone reader, it might want to close the window in // that case. void replyActionFinished(); - public slots: +public slots: void editCurrentMessage(); void annotateMessage(); - private: +private: void updateActions(); void replyCommand(MessageComposer::ReplyStrategy strategy); void addMailingListAction( const QString &item, const KUrl &url ); @@ -113,7 +112,7 @@ void clearMailingListActions(); - private slots: +private slots: void slotItemModified( const Akonadi::Item & item, const QSet< QByteArray > & partIdentifiers ); void slotItemRemoved(const Akonadi::Item& item); @@ -132,7 +131,7 @@ void slotConfigureWebShortcuts(); - private: +private: QList mMailListActionList; QWidget *mParent; Akonadi::Item mCurrentItem; @@ -141,15 +140,13 @@ KActionMenu *mReplyActionMenu; KAction *mReplyAction, *mReplyAllAction, *mReplyAuthorAction, - *mReplyListAction, *mNoQuoteReplyAction, - *mForwardInlineAction, *mForwardAttachedAction, *mRedirectAction; + *mReplyListAction, *mNoQuoteReplyAction, + *mForwardInlineAction, *mForwardAttachedAction, *mRedirectAction; KAction *mCreateTodoAction; KActionMenu *mStatusMenu; KActionMenu *mForwardActionMenu; KActionMenu *mMailingListActionMenu; KAction *mEditAction, *mAnnotateAction, *mPrintAction, *mPrintPreviewAction; - bool mKorganizerIsOnSystem; - Akonadi::Monitor *mMonitor; TemplateParser::CustomTemplatesMenu *mCustomTemplatesMenu; KAction *mListFilterAction; }; diff -Nru kdepim-4.12.97/kmail/searchdialog/searchwindow.cpp kdepim-4.13.0/kmail/searchdialog/searchwindow.cpp --- kdepim-4.12.97/kmail/searchdialog/searchwindow.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/searchdialog/searchwindow.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -175,8 +175,6 @@ connect( mUi.mLbxMatches, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotContextMenuRequested(QPoint)) ); - connect( mUi.mLbxMatches, SIGNAL(clicked(Akonadi::Item)), - this, SLOT(slotShowMsg(Akonadi::Item)) ); connect( mUi.mLbxMatches, SIGNAL(doubleClicked(Akonadi::Item)), this, SLOT(slotViewMsg(Akonadi::Item)) ); connect( mUi.mLbxMatches, SIGNAL(currentChanged(Akonadi::Item)), @@ -673,27 +671,16 @@ slotClose(); } -bool SearchWindow::slotShowMsg( const Akonadi::Item &item ) -{ - if ( item.isValid() ) { - mKMMainWidget->slotMessageSelected( item ); - return true; - } - return false; -} - void SearchWindow::slotViewSelectedMsg() { mKMMainWidget->slotMessageActivated( selectedMessage() ); } -bool SearchWindow::slotViewMsg( const Akonadi::Item &item ) +void SearchWindow::slotViewMsg( const Akonadi::Item &item ) { if ( item.isValid() ) { mKMMainWidget->slotMessageActivated( item ); - return true; } - return false; } void SearchWindow::slotCurrentChanged( const Akonadi::Item &item ) @@ -737,14 +724,15 @@ { const int count = selectedMessages().count(); const bool singleActions = (count == 1); + const bool notEmpty = (count > 0); mReplyAction->setEnabled( singleActions ); mReplyAllAction->setEnabled( singleActions ); mReplyListAction->setEnabled( singleActions ); mPrintAction->setEnabled( singleActions ); - mSaveAtchAction->setEnabled( count > 0 ); - mSaveAsAction->setEnabled( count > 0 ); - mClearAction->setEnabled( count > 0 ); + mSaveAtchAction->setEnabled( notEmpty ); + mSaveAsAction->setEnabled( notEmpty ); + mClearAction->setEnabled( notEmpty ); } void SearchWindow::slotContextMenuRequested( const QPoint& ) diff -Nru kdepim-4.12.97/kmail/searchdialog/searchwindow.h kdepim-4.13.0/kmail/searchdialog/searchwindow.h --- kdepim-4.12.97/kmail/searchdialog/searchwindow.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/searchdialog/searchwindow.h 2014-04-10 07:40:20.000000000 +0000 @@ -125,9 +125,8 @@ void scheduleRename( const QString& ); void renameSearchFolder(); void openSearchFolder(); - bool slotShowMsg( const Akonadi::Item& ); void slotViewSelectedMsg(); - bool slotViewMsg( const Akonadi::Item& ); + void slotViewMsg( const Akonadi::Item& ); void slotCurrentChanged( const Akonadi::Item& ); void updateContextMenuActions(); void slotFolderActivated(); diff -Nru kdepim-4.12.97/kmail/storageservice/storageservicesettingsjob.cpp kdepim-4.13.0/kmail/storageservice/storageservicesettingsjob.cpp --- kdepim-4.12.97/kmail/storageservice/storageservicesettingsjob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/storageservice/storageservicesettingsjob.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -80,21 +80,11 @@ return QLatin1String("https://bugs.kde.org/"); } -QString StorageServiceSettingsJob::ubuntuOneAttachmentVolume() const -{ - return QLatin1String("/~/KMail Attachments"); -} - QString StorageServiceSettingsJob::hubicScope() const { return QLatin1String("usage.r,account.r,credentials.r,links.wd"); } -QString StorageServiceSettingsJob::ubuntuOneTokenName() const -{ - return QLatin1String("kmail"); -} - QString StorageServiceSettingsJob::gdriveClientId() const { //TODO diff -Nru kdepim-4.12.97/kmail/storageservice/storageservicesettingsjob.h kdepim-4.13.0/kmail/storageservice/storageservicesettingsjob.h --- kdepim-4.12.97/kmail/storageservice/storageservicesettingsjob.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kmail/storageservice/storageservicesettingsjob.h 2014-04-10 07:40:20.000000000 +0000 @@ -40,9 +40,7 @@ QString hubicClientSecret() const; QString dropboxRootPath() const; QString oauth2RedirectUrl() const; - QString ubuntuOneAttachmentVolume() const; QString hubicScope() const; - QString ubuntuOneTokenName() const; QString gdriveClientId() const; QString gdriveClientSecret() const; QString defaultUploadFolder() const; diff -Nru kdepim-4.12.97/knotes/data/knote_config_action.desktop kdepim-4.13.0/knotes/data/knote_config_action.desktop --- kdepim-4.12.97/knotes/data/knote_config_action.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/knotes/data/knote_config_action.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -44,7 +44,7 @@ Name[nl]=Acties Name[nn]=Handlingar Name[pa]=ਐਕਸ਼ਨ -Name[pl]=Akcje +Name[pl]=Działania Name[pt]=Acções Name[pt_BR]=Ações Name[ro]=Acțiuni diff -Nru kdepim-4.12.97/knotes/data/knote_config_collection.desktop kdepim-4.13.0/knotes/data/knote_config_collection.desktop --- kdepim-4.12.97/knotes/data/knote_config_collection.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/knotes/data/knote_config_collection.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -12,37 +12,28 @@ X-KDE-CfgDlgHierarchy=KNotes X-KDE-Weight=200 -Name=Collection -Name[bs]=Kolekcija -Name[ca]=Col·lecció -Name[ca@valencia]=Col·lecció -Name[cs]=Sbírka -Name[da]=Samling -Name[de]=Sammlung -Name[el]=Συλλογή -Name[es]=Colección -Name[fi]=Kokoelma -Name[fr]=Collection -Name[gl]=Colección -Name[hu]=Gyűjtemény -Name[ia]=Collection -Name[it]=Collezione -Name[nb]=Samling +Name=Collections +Name[ca]=Col·leccions +Name[cs]=Sbírky +Name[de]=Sammlungen +Name[es]=Colecciones +Name[fi]=Kokoelmat +Name[ia]=Collectiones +Name[it]=Collezioni Name[nds]=Sammeln -Name[nl]=Verzameling -Name[nn]=Samling -Name[pl]=Zbiór -Name[pt]=Colecção -Name[pt_BR]=Coleção -Name[se]=Čoahkádus -Name[sk]=Kolekcia -Name[sr]=Збирка -Name[sr@ijekavian]=Збирка -Name[sr@ijekavianlatin]=Zbirka -Name[sr@latin]=Zbirka -Name[sv]=Samling -Name[uk]=Збірка -Name[x-test]=xxCollectionxx +Name[nl]=Verzamelingen +Name[pl]=Zbiory +Name[pt]=Colecções +Name[pt_BR]=Coleções +Name[ru]=Коллекции +Name[sk]=Kolekcie +Name[sr]=Збирке +Name[sr@ijekavian]=Збирке +Name[sr@ijekavianlatin]=Zbirke +Name[sr@latin]=Zbirke +Name[sv]=Samlingar +Name[uk]=Збірки +Name[x-test]=xxCollectionsxx Name[zh_TW]=收藏 Comment=Setup collections for notes Comment[bs]=Postavna kolekcija za bilješke @@ -65,6 +56,7 @@ Comment[pl]=Ustaw zbiory dla notatek Comment[pt]=Configurar as colecções das notas Comment[pt_BR]=Configurar as coleções das notas +Comment[ru]=Настройка коллекций, хранящих заметки Comment[sk]=Nastavenie kolekcií pre poznámky Comment[sr]=Подесите збирке за белешке Comment[sr@ijekavian]=Подесите збирке за биљешке diff -Nru kdepim-4.12.97/knotes/data/knote_config_editor.desktop kdepim-4.13.0/knotes/data/knote_config_editor.desktop --- kdepim-4.12.97/knotes/data/knote_config_editor.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/knotes/data/knote_config_editor.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -98,7 +98,7 @@ Comment[pt]=Configurar o editor Comment[pt_BR]=Configurar editor Comment[ro]=Configurează editorul -Comment[ru]=Настроить редактор заметок +Comment[ru]=Настройка редактора заметок Comment[sk]=Nastavenie editora Comment[sl]=Nastavitev urejevalnika Comment[sr]=Подесите уређивач diff -Nru kdepim-4.12.97/knotes/data/knote_config_print.desktop kdepim-4.13.0/knotes/data/knote_config_print.desktop --- kdepim-4.12.97/knotes/data/knote_config_print.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/knotes/data/knote_config_print.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -34,6 +34,7 @@ Name[pl]=Drukuj Name[pt]=Imprimir Name[pt_BR]=Imprimir +Name[ru]=Печать Name[sk]=Tlačiť Name[sr]=Штампање Name[sr@ijekavian]=Штампање @@ -66,6 +67,7 @@ Comment[pl]=Ustaw drukowanie dla notatek Comment[pt]=Configurar a impressão das notas Comment[pt_BR]=Configurar a impressão para notas +Comment[ru]=Настройка печати заметок Comment[sk]=Nastavenie tlače pre poznámky Comment[sr]=Подесите штампање за белешке Comment[sr@ijekavian]=Подесите штампање за биљешке diff -Nru kdepim-4.12.97/knotes/data/knotes.notifyrc kdepim-4.13.0/knotes/data/knotes.notifyrc --- kdepim-4.12.97/knotes/data/knotes.notifyrc 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/knotes/data/knotes.notifyrc 2014-04-10 07:40:20.000000000 +0000 @@ -21,6 +21,7 @@ Comment[pl]=notatki Comment[pt]=notas Comment[pt_BR]=notas +Comment[ru]=Заметки Comment[sk]=poznámky Comment[sr]=Белешке Comment[sr@ijekavian]=Белешке @@ -52,6 +53,7 @@ Name[pl]=Otrzymana notatka Name[pt]=Nota recebida Name[pt_BR]=Nota recebida +Name[ru]=Получена заметка Name[sk]=Prijatá poznámka Name[sr]=Примљена белешка Name[sr@ijekavian]=Примљена белешка diff -Nru kdepim-4.12.97/knotes/print/themes/big-title/theme.desktop kdepim-4.13.0/knotes/print/themes/big-title/theme.desktop --- kdepim-4.12.97/knotes/print/themes/big-title/theme.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/knotes/print/themes/big-title/theme.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -20,6 +20,7 @@ Name[pl]=Duży Tytuł Name[pt]=Título Grande Name[pt_BR]=Título grande +Name[ru]=Большой заголовок Name[sk]=Veľký titulok Name[sr]=Велики наслов Name[sr@ijekavian]=Велики наслов @@ -51,6 +52,7 @@ Description[pl]=Motyw drukowania KNote z dużym tytułem Description[pt]=Tema de impressão do KNotes com títulos grandes Description[pt_BR]=Tema de impressão do KNotes com títulos grandes +Description[ru]=Оформление для печати заметок с большим заголовком Description[sk]=Tlačová téma KNote s veľkým titulkom Description[sr]=Тема за штампање из К‑бележака са великим насловом Description[sr@ijekavian]=Тема за штампање из К‑биљежака са великим насловом diff -Nru kdepim-4.12.97/knotes/print/themes/default/theme.desktop kdepim-4.13.0/knotes/print/themes/default/theme.desktop --- kdepim-4.12.97/knotes/print/themes/default/theme.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/knotes/print/themes/default/theme.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -87,6 +87,7 @@ Description[pl]=Domyślny motyw drukowania knotes Description[pt]=O tema de impressão predefinido do KNotes. Description[pt_BR]=Tema de impressão padrão do KNotes +Description[ru]=Оформление для печати заметок по умолчанию Description[sk]=Predvolená tlačová téma knotes Description[sr]=Подразумевана тема за штампање из К‑бележака. Description[sr@ijekavian]=Подразумевана тема за штампање из К‑биљежака. diff -Nru kdepim-4.12.97/kontact/plugins/knotes/kcmknotessummary.desktop kdepim-4.13.0/kontact/plugins/knotes/kcmknotessummary.desktop --- kdepim-4.12.97/kontact/plugins/knotes/kcmknotessummary.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kontact/plugins/knotes/kcmknotessummary.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -32,6 +32,7 @@ Name[pl]=Nowe notatki Name[pt]=Novas Notas Name[pt_BR]=Novas notas +Name[ru]=Новые заметки Name[sk]=Nové poznámky Name[sr]=Нове белешке Name[sr@ijekavian]=Нове белешке @@ -62,6 +63,7 @@ Comment[pl]=Ustawienia podsumowania notatek Comment[pt]=Configuração do Resumo das Notas Comment[pt_BR]=Configuração do resumo de notas +Comment[ru]=Настройка дайджеста заметок Comment[sk]=Nastavenie súhrnu poznámok Comment[sr]=Подешавање сажетка бележака Comment[sr@ijekavian]=Подешавање сажетка бележака @@ -91,6 +93,7 @@ X-KDE-Keywords[pl]=notatki, podsumowanie, konfiguruj, ustawienia X-KDE-Keywords[pt]=notas, resumo, configurar, configuração X-KDE-Keywords[pt_BR]=notas, resumo, configurar, configurações +X-KDE-Keywords[ru]=notes,email,summary,configure,settings,заметки,настройка,сводка,почта,дайджест,почта X-KDE-Keywords[sk]=email, súhrn, nastaviť, nastavenia X-KDE-Keywords[sr]=notes,summary,configure,settings,белешке,сажетак,подешавање,подесити,поставке X-KDE-Keywords[sr@ijekavian]=notes,summary,configure,settings,белешке,сажетак,подешавање,подесити,поставке diff -Nru kdepim-4.12.97/kontact/plugins/knotes/summarywidget.cpp kdepim-4.13.0/kontact/plugins/knotes/summarywidget.cpp --- kdepim-4.12.97/kontact/plugins/knotes/summarywidget.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/kontact/plugins/knotes/summarywidget.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -114,12 +114,24 @@ return; mInProgress = true; qDeleteAll( mLabels ); - int counter = 0; mLabels.clear(); + int counter = 0; + mModelState->restoreState(); displayNotes(QModelIndex(), counter); - qDebug()<<"void KNotesSummaryWidget::updateFolderList() "; mInProgress = false; + + if ( counter == 0 ) { + QLabel *label = new QLabel( i18n( "No note found" ), this ); + label->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter ); + mLayout->addWidget( label, 0, 0 ); + mLabels.append( label ); + } + QList::const_iterator lit; + QList::const_iterator lend( mLabels.constEnd() ); + for ( lit = mLabels.constBegin(); lit != lend; ++lit ) { + (*lit)->show(); + } } void KNotesSummaryWidget::displayNotes( const QModelIndex &parent, int &counter) @@ -131,7 +143,7 @@ mModelProxy->data( child, Akonadi::EntityTreeModel::ItemRole ).value(); if (item.isValid()) { - qDebug()<<" createNote "; + qDebug()<<" createNote "<part() ); + plugin->shortcutChanged(); + setCaption( i18nc( "@title:window Plugin dependent window title", "%1 - Kontact", plugin->title() ) ); diff -Nru kdepim-4.12.97/korganizer/kcmconfigs/korganizer_configcolorsandfonts.desktop kdepim-4.13.0/korganizer/kcmconfigs/korganizer_configcolorsandfonts.desktop --- kdepim-4.12.97/korganizer/kcmconfigs/korganizer_configcolorsandfonts.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/korganizer/kcmconfigs/korganizer_configcolorsandfonts.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -25,7 +25,7 @@ Name[en_GB]=Colours and Fonts Name[es]=Colores y tipos de letra Name[et]=Värvid ja fondid -Name[fi]=Värit ja kirjasimet +Name[fi]=Värit ja fontit Name[fr]=Couleurs et polices Name[ga]=Dathanna agus Clónna Name[gl]=Cores e tipos de letra @@ -76,7 +76,7 @@ Comment[es]=Configuración de los colores y tipos de letra de KOrganizer Comment[et]=KOrganizeri värvide ja fontide seadistamine Comment[fa]=پیکربندی رنگها و قلمهای KOrganizer -Comment[fi]=KOrganizerin värien asetukset +Comment[fi]=KOrganizerin väri- ja fonttiasetukset Comment[fr]=Configuration des couleurs et des polices de KOrganizer Comment[ga]=Cumraíocht na nDathanna/gClónna le haghaidh KOrganizer Comment[gl]=Configuración das cores e dos tipos de letra do KOrganizer diff -Nru kdepim-4.12.97/libkdepim/addressline/addresseelineedit.cpp kdepim-4.13.0/libkdepim/addressline/addresseelineedit.cpp --- kdepim-4.12.97/libkdepim/addressline/addresseelineedit.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/addressline/addresseelineedit.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -42,6 +42,7 @@ #include #include +#include #include @@ -73,28 +74,28 @@ using namespace KPIM; namespace KPIM { - typedef QMap< QString, QPair > CompletionItemsMap; +typedef QMap< QString, QPair > CompletionItemsMap; } class AddresseeLineEditStatic { - public: +public: AddresseeLineEditStatic() - : completion( new KMailCompletion ), - ldapTimer( 0 ), - ldapSearch( 0 ), - ldapLineEdit( 0 ), - akonadiSession( new Akonadi::Session("contactsCompletionSession") ), - balooCompletionSource( 0 ) + : completion( new KMailCompletion ), + ldapTimer( 0 ), + ldapSearch( 0 ), + ldapLineEdit( 0 ), + akonadiSession( new Akonadi::Session("contactsCompletionSession") ), + balooCompletionSource( 0 ) { } ~AddresseeLineEditStatic() { - delete completion; - delete ldapTimer; - delete ldapSearch; + delete completion; + delete ldapTimer; + delete ldapSearch; } void slotEditCompletionOrder() @@ -107,37 +108,37 @@ void updateLDAPWeights() { - /* Add completion sources for all ldap server, 0 to n. Added first so + /* Add completion sources for all ldap server, 0 to n. Added first so * that they map to the LdapClient::clientNumber() */ - ldapSearch->updateCompletionWeights(); - int clientIndex = 0; - foreach ( const KLDAP::LdapClient *client, ldapSearch->clients() ) { - const int sourceIndex = - addCompletionSource( i18n( "LDAP server: %1" ,client->server().host()), - client->completionWeight() ); + ldapSearch->updateCompletionWeights(); + int clientIndex = 0; + foreach ( const KLDAP::LdapClient *client, ldapSearch->clients() ) { + const int sourceIndex = + addCompletionSource( i18n( "LDAP server: %1" ,client->server().host()), + client->completionWeight() ); - ldapClientToCompletionSourceMap.insert( clientIndex, sourceIndex ); + ldapClientToCompletionSourceMap.insert( clientIndex, sourceIndex ); - clientIndex++; - } + ++clientIndex; + } } int addCompletionSource( const QString &source, int weight ) { - QMap::iterator it = completionSourceWeights.find( source ); - if ( it == completionSourceWeights.end() ) { - completionSourceWeights.insert( source, weight ); - } else { - completionSourceWeights[source] = weight; - } - - const int sourceIndex = completionSources.indexOf( source ); - if ( sourceIndex == -1 ) { - completionSources.append( source ); - return completionSources.size() - 1; - } else { - return sourceIndex; - } + QMap::iterator it = completionSourceWeights.find( source ); + if ( it == completionSourceWeights.end() ) { + completionSourceWeights.insert( source, weight ); + } else { + completionSourceWeights[source] = weight; + } + + const int sourceIndex = completionSources.indexOf( source ); + if ( sourceIndex == -1 ) { + completionSources.append( source ); + return completionSources.size() - 1; + } else { + return sourceIndex; + } } void removeCompletionSource( const QString &source ) @@ -177,60 +178,62 @@ // needs to be unique, but the actual name doesn't matter much static QString newLineEditObjectName() { - static int s_count = 0; - QString name( QLatin1String("KPIM::AddresseeLineEdit") ); - if ( s_count++ ) { - name += QLatin1Char('-'); - name += QString::number( s_count ); - } - return name; + static int s_count = 0; + QString name( QLatin1String("KPIM::AddresseeLineEdit") ); + if ( s_count++ ) { + name += QLatin1Char('-'); + name += QString::number( s_count ); + } + return name; } static const QString s_completionItemIndentString = QLatin1String(" "); static bool itemIsHeader( const QListWidgetItem *item ) { - return item && !item->text().startsWith( s_completionItemIndentString ); + return item && !item->text().startsWith( s_completionItemIndentString ); } class SourceWithWeight { - public: +public: int weight; // the weight of the source QString sourceName; // the name of the source, e.g. "LDAP Server" int index; // index into s_static->completionSources bool operator< ( const SourceWithWeight &other ) const { - if ( weight > other.weight ) { - return true; - } - - if ( weight < other.weight ) { - return false; - } + if ( weight > other.weight ) { + return true; + } + + if ( weight < other.weight ) { + return false; + } - return sourceName < other.sourceName; + return sourceName < other.sourceName; } }; class AddresseeLineEdit::Private { - public: +public: Private( AddresseeLineEdit *qq, bool enableCompletion ) - : q( qq ), - m_useCompletion( enableCompletion ), - m_completionInitialized( false ), - m_smartPaste( false ), - m_addressBookConnected( false ), - m_lastSearchMode( false ), - m_searchExtended( false ), - m_useSemicolonAsSeparator( false ) + : q( qq ), + m_useCompletion( enableCompletion ), + m_completionInitialized( false ), + m_smartPaste( false ), + m_addressBookConnected( false ), + m_lastSearchMode( false ), + m_searchExtended( false ), + m_useSemicolonAsSeparator( false ) { m_delayedQueryTimer.setSingleShot(true); connect( &m_delayedQueryTimer, SIGNAL(timeout()), q, SLOT(slotTriggerDelayedQueries()) ); } + QStringList cleanupBalooContact(const QStringList &lst); + void alternateColor(); void init(); void startLoadingLDAPEntries(); void stopLDAPLookup(); @@ -269,289 +272,313 @@ bool m_searchExtended; //has \" been added? bool m_useSemicolonAsSeparator; QTimer m_delayedQueryTimer; + QColor m_alternateColor; }; void AddresseeLineEdit::Private::init() { - if ( !s_static.exists() ) { - s_static->completion->setOrder( completionOrder() ); - s_static->completion->setIgnoreCase( true ); - } - - if ( m_useCompletion ) { - if ( !s_static->ldapTimer ) { - s_static->ldapTimer = new QTimer; - s_static->ldapSearch = new KLDAP::LdapClientSearch; - + if ( !s_static.exists() ) { + s_static->completion->setOrder( completionOrder() ); + s_static->completion->setIgnoreCase( true ); } - s_static->balooCompletionSource = q->addCompletionSource( i18nc( "@title:group", "Contacts found in your data"), -1 ); + if ( m_useCompletion ) { + if ( !s_static->ldapTimer ) { + s_static->ldapTimer = new QTimer; + s_static->ldapSearch = new KLDAP::LdapClientSearch; - s_static->updateLDAPWeights(); + } - if ( !m_completionInitialized ) { - q->setCompletionObject( s_static->completion, false ); - q->connect( q, SIGNAL(completion(QString)), - q, SLOT(slotCompletion()) ); - q->connect( q, SIGNAL(returnPressed(QString)), - q, SLOT(slotReturnPressed(QString)) ); + s_static->balooCompletionSource = q->addCompletionSource( i18nc( "@title:group", "Contacts found in your data"), -1 ); - KCompletionBox *box = q->completionBox(); - q->connect( box, SIGNAL(activated(QString)), - q, SLOT(slotPopupCompletion(QString)) ); - q->connect( box, SIGNAL(userCancelled(QString)), - q, SLOT(slotUserCancelled(QString)) ); + s_static->updateLDAPWeights(); - q->connect( s_static->ldapTimer, SIGNAL(timeout()), SLOT(slotStartLDAPLookup()) ); - q->connect( s_static->ldapSearch, SIGNAL(searchData(KLDAP::LdapResult::List)), - SLOT(slotLDAPSearchData(KLDAP::LdapResult::List)) ); + if ( !m_completionInitialized ) { + q->setCompletionObject( s_static->completion, false ); + q->connect( q, SIGNAL(completion(QString)), + q, SLOT(slotCompletion()) ); + q->connect( q, SIGNAL(returnPressed(QString)), + q, SLOT(slotReturnPressed(QString)) ); + + KCompletionBox *box = q->completionBox(); + q->connect( box, SIGNAL(activated(QString)), + q, SLOT(slotPopupCompletion(QString)) ); + q->connect( box, SIGNAL(userCancelled(QString)), + q, SLOT(slotUserCancelled(QString)) ); + + q->connect( s_static->ldapTimer, SIGNAL(timeout()), SLOT(slotStartLDAPLookup()) ); + q->connect( s_static->ldapSearch, SIGNAL(searchData(KLDAP::LdapResult::List)), + SLOT(slotLDAPSearchData(KLDAP::LdapResult::List)) ); - m_completionInitialized = true; + m_completionInitialized = true; + } } - } } void AddresseeLineEdit::Private::startLoadingLDAPEntries() { - QString text( s_static->ldapText ); + QString text( s_static->ldapText ); + + // TODO cache last? + QString prevAddr; + const int index = text.lastIndexOf( QLatin1Char( ',' ) ); + if ( index >= 0 ) { + prevAddr = text.left( index + 1 ) + QLatin1Char( ' ' ); + text = text.mid( index + 1, 255 ).trimmed(); + } - // TODO cache last? - QString prevAddr; - const int index = text.lastIndexOf( QLatin1Char( ',' ) ); - if ( index >= 0 ) { - prevAddr = text.left( index + 1 ) + QLatin1Char( ' ' ); - text = text.mid( index + 1, 255 ).trimmed(); - } - - if ( text.isEmpty() ) { - return; - } + if ( text.isEmpty() ) { + return; + } - s_static->ldapSearch->startSearch( text ); + s_static->ldapSearch->startSearch( text ); } void AddresseeLineEdit::Private::stopLDAPLookup() { - s_static->ldapSearch->cancelSearch(); - s_static->ldapLineEdit = 0; + s_static->ldapSearch->cancelSearch(); + s_static->ldapLineEdit = 0; +} + +QStringList AddresseeLineEdit::Private::cleanupBalooContact(const QStringList &lst) +{ + if (lst.isEmpty()) + return lst; + QHash hashEmail; + Q_FOREACH (const QString &email, lst) { + if (!hashEmail.contains(email.toLower())) { + hashEmail.insert(email.toLower(), email); + } + } + return hashEmail.keys(); } void AddresseeLineEdit::Private::searchInBaloo() { - Baloo::PIM::ContactCompleter com(m_searchString.trimmed(), 20); - Q_FOREACH (const QString& email, com.complete()) { - addCompletionItem(email, 1, s_static->balooCompletionSource); - } - doCompletion( m_lastSearchMode ); - // if ( q->hasFocus() || q->completionBox()->hasFocus() ) { - //} + Baloo::PIM::ContactCompleter com(m_searchString.trimmed(), 20); + const QStringList listEmail = cleanupBalooContact(com.complete()); + Q_FOREACH (const QString& email, listEmail) { + addCompletionItem(email, 1, s_static->balooCompletionSource); + } + doCompletion( m_lastSearchMode ); + // if ( q->hasFocus() || q->completionBox()->hasFocus() ) { + //} } +void AddresseeLineEdit::Private::alternateColor() +{ + const KColorScheme colorScheme( QPalette::Active, KColorScheme::View ); + m_alternateColor = colorScheme.background(KColorScheme::AlternateBackground).color(); +} void AddresseeLineEdit::Private::setCompletedItems( const QStringList &items, bool autoSuggest ) { - KCompletionBox *completionBox = q->completionBox(); + KCompletionBox *completionBox = q->completionBox(); - if ( !items.isEmpty() && - !( items.count() == 1 && m_searchString == items.first() ) ) { + if ( !items.isEmpty() && + !( items.count() == 1 && m_searchString == items.first() ) ) { - completionBox->clear(); - const int numberOfItems( items.count() ); - for ( int i = 0; i< numberOfItems; ++i ) - { - QListWidgetItem *item =new QListWidgetItem(items.at( i ), completionBox); - if ( !items.at( i ).startsWith( s_completionItemIndentString ) ) - item->setFlags( item->flags()&~Qt::ItemIsSelectable ); - completionBox->addItem( item ); - } - if ( !completionBox->isVisible() ) { - if ( !m_searchString.isEmpty() ) { - completionBox->setCancelledText( m_searchString ); - } - completionBox->popup(); - // we have to install the event filter after popup(), since that - // calls show(), and that's where KCompletionBox installs its filter. - // We want to be first, though, so do it now. - if ( s_static->completion->order() == KCompletion::Weighted ) { - qApp->installEventFilter( q ); - } - } - - QListWidgetItem *item = completionBox->item( 1 ); - if ( item ) { - completionBox->blockSignals( true ); - completionBox->setCurrentItem( item ); - item->setSelected( true ); - completionBox->blockSignals( false ); - } - - if ( autoSuggest ) { - const int index = items.first().indexOf( m_searchString ); - const QString newText = items.first().mid( index ); - q->setUserSelection( false ); - q->setCompletedText( newText, true ); - } - } else { - if ( completionBox && completionBox->isVisible() ) { - completionBox->hide(); - completionBox->setItems( QStringList() ); + completionBox->clear(); + const int numberOfItems( items.count() ); + for ( int i = 0; i< numberOfItems; ++i ) + { + QListWidgetItem *item =new QListWidgetItem(items.at( i ), completionBox); + if ( !items.at( i ).startsWith( s_completionItemIndentString ) ) { + if (!m_alternateColor.isValid()) { + alternateColor(); + } + item->setBackgroundColor(m_alternateColor); + } + completionBox->addItem( item ); + } + if ( !completionBox->isVisible() ) { + if ( !m_searchString.isEmpty() ) { + completionBox->setCancelledText( m_searchString ); + } + completionBox->popup(); + // we have to install the event filter after popup(), since that + // calls show(), and that's where KCompletionBox installs its filter. + // We want to be first, though, so do it now. + if ( s_static->completion->order() == KCompletion::Weighted ) { + qApp->installEventFilter( q ); + } + } + + QListWidgetItem *item = completionBox->item( 1 ); + if ( item ) { + completionBox->blockSignals( true ); + completionBox->setCurrentItem( item ); + item->setSelected( true ); + completionBox->blockSignals( false ); + } + + if ( autoSuggest ) { + const int index = items.first().indexOf( m_searchString ); + const QString newText = items.first().mid( index ); + q->setUserSelection( false ); + q->setCompletedText( newText, true ); + } + } else { + if ( completionBox && completionBox->isVisible() ) { + completionBox->hide(); + completionBox->setItems( QStringList() ); + } } - } } void AddresseeLineEdit::Private::addCompletionItem( const QString &string, int weight, int completionItemSource, const QStringList *keyWords ) { - // Check if there is an exact match for item already, and use the - // maximum weight if so. Since there's no way to get the information - // from KCompletion, we have to keep our own QMap. - // We also update the source since the item should always be shown from the source with the highest weight - - CompletionItemsMap::iterator it = s_static->completionItemMap.find( string ); - if ( it != s_static->completionItemMap.end() ) { - weight = qMax( ( *it ).first, weight ); - ( *it ).first = weight; - ( *it ).second = completionItemSource; - } else { - s_static->completionItemMap.insert( string, qMakePair( weight, completionItemSource ) ); - } - - s_static->completion->addItem(string, weight); - if (keyWords && !keyWords->isEmpty()) - s_static->completion->addItemWithKeys(string, weight, keyWords); // see kmailcompletion.cpp + // Check if there is an exact match for item already, and use the + // maximum weight if so. Since there's no way to get the information + // from KCompletion, we have to keep our own QMap. + // We also update the source since the item should always be shown from the source with the highest weight + + CompletionItemsMap::iterator it = s_static->completionItemMap.find( string ); + if ( it != s_static->completionItemMap.end() ) { + weight = qMax( ( *it ).first, weight ); + ( *it ).first = weight; + ( *it ).second = completionItemSource; + } else { + s_static->completionItemMap.insert( string, qMakePair( weight, completionItemSource ) ); + } + + s_static->completion->addItem(string, weight); + if (keyWords && !keyWords->isEmpty()) + s_static->completion->addItemWithKeys(string, weight, keyWords); // see kmailcompletion.cpp } const QStringList KPIM::AddresseeLineEdit::Private::adjustedCompletionItems( bool fullSearch ) { - QStringList items = fullSearch ? - s_static->completion->allMatches( m_searchString ) : - s_static->completion->substringCompletion( m_searchString ); - - //force items to be sorted by email - items.sort(); - - // For weighted mode, the algorithm is the following: - // In the first loop, we add each item to its section (there is one section per completion source) - // We also add spaces in front of the items. - // The sections are appended to the items list. - // In the second loop, we then walk through the sections and add all the items in there to the - // sorted item list, which is the final result. - // - // The algo for non-weighted mode is different. - - int lastSourceIndex = -1; - unsigned int i = 0; - - // Maps indices of the items list, which are section headers/source items, - // to a QStringList which are the items of that section/source. - QMap sections; - QStringList sortedItems; - for ( QStringList::Iterator it = items.begin(); it != items.end(); ++it, ++i ) { - CompletionItemsMap::const_iterator cit = s_static->completionItemMap.constFind( *it ); - if ( cit == s_static->completionItemMap.constEnd() ) { - continue; - } + QStringList items = fullSearch ? + s_static->completion->allMatches( m_searchString ) : + s_static->completion->substringCompletion( m_searchString ); + + //force items to be sorted by email + items.sort(); + + // For weighted mode, the algorithm is the following: + // In the first loop, we add each item to its section (there is one section per completion source) + // We also add spaces in front of the items. + // The sections are appended to the items list. + // In the second loop, we then walk through the sections and add all the items in there to the + // sorted item list, which is the final result. + // + // The algo for non-weighted mode is different. + + int lastSourceIndex = -1; + unsigned int i = 0; + + // Maps indices of the items list, which are section headers/source items, + // to a QStringList which are the items of that section/source. + QMap sections; + QStringList sortedItems; + for ( QStringList::Iterator it = items.begin(); it != items.end(); ++it, ++i ) { + CompletionItemsMap::const_iterator cit = s_static->completionItemMap.constFind( *it ); + if ( cit == s_static->completionItemMap.constEnd() ) { + continue; + } + + const int index = (*cit).second; + + if ( s_static->completion->order() == KCompletion::Weighted ) { + if ( lastSourceIndex == -1 || lastSourceIndex != index ) { + const QString sourceLabel( s_static->completionSources.at( index ) ); + if ( sections.find( index ) == sections.end() ) { + it = items.insert( it, sourceLabel ); + ++it; //skip new item + } + lastSourceIndex = index; + } + + (*it) = (*it).prepend( s_completionItemIndentString ); + // remove preferred email sort added in addContact() + (*it).replace( QLatin1String( " <" ), QLatin1String( " <" ) ); + } + sections[ index ].append( *it ); - const int index = (*cit).second; + if ( s_static->completion->order() == KCompletion::Sorted ) { + sortedItems.append( *it ); + } + } if ( s_static->completion->order() == KCompletion::Weighted ) { - if ( lastSourceIndex == -1 || lastSourceIndex != index ) { - const QString sourceLabel( s_static->completionSources[ index ] ); - if ( sections.find( index ) == sections.end() ) { - it = items.insert( it, sourceLabel ); - ++it; //skip new item - } - lastSourceIndex = index; - } - - (*it) = (*it).prepend( s_completionItemIndentString ); - // remove preferred email sort added in addContact() - (*it).replace( QLatin1String( " <" ), QLatin1String( " <" ) ); - } - sections[ index ].append( *it ); - - if ( s_static->completion->order() == KCompletion::Sorted ) { - sortedItems.append( *it ); - } - } - - if ( s_static->completion->order() == KCompletion::Weighted ) { - - // Sort the sections - QList sourcesAndWeights; - const int numberOfCompletionSources(s_static->completionSources.size()); - for ( int i = 0; i < numberOfCompletionSources; ++i ) { - SourceWithWeight sww; - sww.sourceName = s_static->completionSources[i]; - sww.weight = s_static->completionSourceWeights[sww.sourceName]; - sww.index = i; - sourcesAndWeights.append( sww ); - } - qSort( sourcesAndWeights.begin(), sourcesAndWeights.end() ); - - // Add the sections and their items to the final sortedItems result list - const int numberOfSources(sourcesAndWeights.size()); - for ( int i = 0; i < numberOfSources; ++i ) { - const QStringList sectionItems = sections[sourcesAndWeights[i].index]; - if ( !sectionItems.isEmpty() ) { - sortedItems.append( sourcesAndWeights[i].sourceName ); - foreach ( const QString &itemInSection, sectionItems ) { - sortedItems.append( itemInSection ); - } - } - } - } else { - sortedItems.sort(); - } - return sortedItems; + // Sort the sections + QList sourcesAndWeights; + const int numberOfCompletionSources(s_static->completionSources.size()); + for ( int i = 0; i < numberOfCompletionSources; ++i ) { + SourceWithWeight sww; + sww.sourceName = s_static->completionSources.at(i); + sww.weight = s_static->completionSourceWeights[sww.sourceName]; + sww.index = i; + sourcesAndWeights.append( sww ); + } + qSort( sourcesAndWeights.begin(), sourcesAndWeights.end() ); + + // Add the sections and their items to the final sortedItems result list + const int numberOfSources(sourcesAndWeights.size()); + for ( int i = 0; i < numberOfSources; ++i ) { + const QStringList sectionItems = sections[sourcesAndWeights[i].index]; + if ( !sectionItems.isEmpty() ) { + sortedItems.append( sourcesAndWeights[i].sourceName ); + foreach ( const QString &itemInSection, sectionItems ) { + sortedItems.append( itemInSection ); + } + } + } + } else { + sortedItems.sort(); + } + + return sortedItems; } void AddresseeLineEdit::Private::updateSearchString() { - m_searchString = q->text(); + m_searchString = q->text(); - int n = -1; - bool inQuote = false; - uint searchStringLength = m_searchString.length(); - for ( uint i = 0; i < searchStringLength; ++i ) { - const QChar searchChar = m_searchString[ i ]; - if ( searchChar == QLatin1Char( '"' ) ) { - inQuote = !inQuote; - } + int n = -1; + bool inQuote = false; + const int searchStringLength = m_searchString.length(); + for ( int i = 0; i < searchStringLength; ++i ) { + const QChar searchChar = m_searchString.at( i ); + if ( searchChar == QLatin1Char( '"' ) ) { + inQuote = !inQuote; + } - if ( searchChar == QLatin1Char('\\') && - ( i + 1 ) < searchStringLength && m_searchString[ i + 1 ] == QLatin1Char( '"' ) ) { - ++i; - } + if ( searchChar == QLatin1Char('\\') && + ( i + 1 ) < searchStringLength && m_searchString.at( i + 1 ) == QLatin1Char( '"' ) ) { + ++i; + } - if ( inQuote ) { - continue; - } + if ( inQuote ) { + continue; + } - if ( i < searchStringLength && - ( searchChar == QLatin1Char(',') || - ( m_useSemicolonAsSeparator && searchChar == QLatin1Char(';') ) ) ) { - n = i; + if ( i < searchStringLength && + ( searchChar == QLatin1Char(',') || + ( m_useSemicolonAsSeparator && searchChar == QLatin1Char(';') ) ) ) { + n = i; + } } - } - if ( n >= 0 ) { - ++n; // Go past the "," + if ( n >= 0 ) { + ++n; // Go past the "," - const int len = m_searchString.length(); + const int len = m_searchString.length(); - // Increment past any whitespace... - while ( n < len && m_searchString[ n ].isSpace() ) { - ++n; - } + // Increment past any whitespace... + while ( n < len && m_searchString.at( n ).isSpace() ) { + ++n; + } - m_previousAddresses = m_searchString.left( n ); - m_searchString = m_searchString.mid( n ).trimmed(); - } else { - m_previousAddresses.clear(); - } + m_previousAddresses = m_searchString.left( n ); + m_searchString = m_searchString.mid( n ).trimmed(); + } else { + m_previousAddresses.clear(); + } } void AddresseeLineEdit::Private::slotTriggerDelayedQueries() @@ -576,278 +603,278 @@ void AddresseeLineEdit::Private::akonadiPerformSearch() { - if ( m_searchString.size() < 2 ) { - return; - } - kDebug() << "searching akonadi with:" << m_searchString; - - // first, kill all job still in flight, they are no longer current - Q_FOREACH( QWeakPointer job, s_static->akonadiJobsInFlight ) { - if ( !job.isNull() ) { - job.data()->kill(); - } - } - s_static->akonadiJobsInFlight.clear(); - - // now start new jobs - Akonadi::ContactSearchJob *contactJob = new Akonadi::ContactSearchJob( s_static->akonadiSession ); - contactJob->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent ); - contactJob->setQuery( Akonadi::ContactSearchJob::NameOrEmail, m_searchString, - Akonadi::ContactSearchJob::ContainsWordBoundaryMatch ); - q->connect( contactJob, SIGNAL(itemsReceived(Akonadi::Item::List)), - q, SLOT(slotAkonadiHandleItems(Akonadi::Item::List)) ); - q->connect( contactJob, SIGNAL(result(KJob*)), - q, SLOT(slotAkonadiSearchResult(KJob*)) ); - - Akonadi::ContactGroupSearchJob *groupJob = new Akonadi::ContactGroupSearchJob( s_static->akonadiSession ); - groupJob->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent ); - groupJob->setQuery( Akonadi::ContactGroupSearchJob::Name, m_searchString, - Akonadi::ContactGroupSearchJob::ContainsMatch ); - q->connect( contactJob, SIGNAL(itemsReceived(Akonadi::Item::List)), - q, SLOT(slotAkonadiHandleItems(Akonadi::Item::List)) ); - q->connect( groupJob, SIGNAL(result(KJob*)), - q, SLOT(slotAkonadiSearchResult(KJob*)) ); - - s_static->akonadiJobsInFlight.append( contactJob ); - s_static->akonadiJobsInFlight.append( groupJob ); - akonadiHandlePending(); + if ( m_searchString.size() < 2 ) { + return; + } + kDebug() << "searching akonadi with:" << m_searchString; + + // first, kill all job still in flight, they are no longer current + Q_FOREACH( QWeakPointer job, s_static->akonadiJobsInFlight ) { + if ( !job.isNull() ) { + job.data()->kill(); + } + } + s_static->akonadiJobsInFlight.clear(); + + // now start new jobs + Akonadi::ContactSearchJob *contactJob = new Akonadi::ContactSearchJob( s_static->akonadiSession ); + contactJob->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent ); + contactJob->setQuery( Akonadi::ContactSearchJob::NameOrEmail, m_searchString, + Akonadi::ContactSearchJob::ContainsWordBoundaryMatch ); + q->connect( contactJob, SIGNAL(itemsReceived(Akonadi::Item::List)), + q, SLOT(slotAkonadiHandleItems(Akonadi::Item::List)) ); + q->connect( contactJob, SIGNAL(result(KJob*)), + q, SLOT(slotAkonadiSearchResult(KJob*)) ); + + Akonadi::ContactGroupSearchJob *groupJob = new Akonadi::ContactGroupSearchJob( s_static->akonadiSession ); + groupJob->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent ); + groupJob->setQuery( Akonadi::ContactGroupSearchJob::Name, m_searchString, + Akonadi::ContactGroupSearchJob::ContainsMatch ); + q->connect( contactJob, SIGNAL(itemsReceived(Akonadi::Item::List)), + q, SLOT(slotAkonadiHandleItems(Akonadi::Item::List)) ); + q->connect( groupJob, SIGNAL(result(KJob*)), + q, SLOT(slotAkonadiSearchResult(KJob*)) ); + + s_static->akonadiJobsInFlight.append( contactJob ); + s_static->akonadiJobsInFlight.append( groupJob ); + akonadiHandlePending(); } void AddresseeLineEdit::Private::akonadiHandlePending() { - kDebug() << "Pending items: " << s_static->akonadiPendingItems.size(); - Akonadi::Item::List::iterator it = s_static->akonadiPendingItems.begin(); - while ( it != s_static->akonadiPendingItems.end() ) { - const Akonadi::Item item = *it; - - const int sourceIndex = - s_static->akonadiCollectionToCompletionSourceMap.value( item.parentCollection().id(), -1 ); - if ( sourceIndex >= 0 ) { - kDebug() << "identified collection: " << s_static->completionSources[sourceIndex]; - q->addItem( item, 1, sourceIndex ); + kDebug() << "Pending items: " << s_static->akonadiPendingItems.size(); + Akonadi::Item::List::iterator it = s_static->akonadiPendingItems.begin(); + while ( it != s_static->akonadiPendingItems.end() ) { + const Akonadi::Item item = *it; - // remove from the pending - it = s_static->akonadiPendingItems.erase( it ); - } else { - ++it; + const int sourceIndex = + s_static->akonadiCollectionToCompletionSourceMap.value( item.parentCollection().id(), -1 ); + if ( sourceIndex >= 0 ) { + kDebug() << "identified collection: " << s_static->completionSources[sourceIndex]; + q->addItem( item, 1, sourceIndex ); + + // remove from the pending + it = s_static->akonadiPendingItems.erase( it ); + } else { + ++it; + } } - } } void AddresseeLineEdit::Private::doCompletion( bool ctrlT ) { - m_lastSearchMode = ctrlT; + m_lastSearchMode = ctrlT; - const KGlobalSettings::Completion mode = q->completionMode(); + const KGlobalSettings::Completion mode = q->completionMode(); - if ( mode == KGlobalSettings::CompletionNone ) { - return; - } + if ( mode == KGlobalSettings::CompletionNone ) { + return; + } - s_static->completion->setOrder( completionOrder() ); + s_static->completion->setOrder( completionOrder() ); + + // cursor at end of string - or Ctrl+T pressed for substring completion? + if ( ctrlT ) { + const QStringList completions = adjustedCompletionItems( false ); + + if ( completions.count() > 1 ) { + ; //m_previousAddresses = prevAddr; + } else if ( completions.count() == 1 ) { + q->setText( m_previousAddresses + completions.first().trimmed() ); + } - // cursor at end of string - or Ctrl+T pressed for substring completion? - if ( ctrlT ) { - const QStringList completions = adjustedCompletionItems( false ); + // Make sure the completion popup is closed if no matching items were found + setCompletedItems( completions, true ); - if ( completions.count() > 1 ) { - ; //m_previousAddresses = prevAddr; - } else if ( completions.count() == 1 ) { - q->setText( m_previousAddresses + completions.first().trimmed() ); + q->cursorAtEnd(); + q->setCompletionMode( mode ); //set back to previous mode + return; } - // Make sure the completion popup is closed if no matching items were found - setCompletedItems( completions, true ); + switch ( mode ) { + case KGlobalSettings::CompletionPopupAuto: + { + if ( m_searchString.isEmpty() ) { + break; + } + //else: fall-through to the CompletionPopup case + } - q->cursorAtEnd(); - q->setCompletionMode( mode ); //set back to previous mode - return; - } - - switch ( mode ) { - case KGlobalSettings::CompletionPopupAuto: - { - if ( m_searchString.isEmpty() ) { - break; - } - //else: fall-through to the CompletionPopup case - } - - case KGlobalSettings::CompletionPopup: - { - const QStringList items = adjustedCompletionItems( false ); - setCompletedItems( items, false ); - } - break; - - case KGlobalSettings::CompletionShell: - { - const QString match = s_static->completion->makeCompletion( m_searchString ); - if ( !match.isNull() && match != m_searchString ) { - q->setText( m_previousAddresses + match ); - q->setModified( true ); - q->cursorAtEnd(); - } - } - break; - - case KGlobalSettings::CompletionMan: // Short-Auto in fact - case KGlobalSettings::CompletionAuto: - { - //force autoSuggest in KLineEdit::keyPressed or setCompletedText will have no effect - q->setCompletionMode( q->completionMode() ); - - if ( !m_searchString.isEmpty() ) { - - //if only our \" is left, remove it since user has not typed it either - if ( m_searchExtended && m_searchString == QLatin1String( "\"" ) ) { - m_searchExtended = false; - m_searchString.clear(); - q->setText( m_previousAddresses ); + case KGlobalSettings::CompletionPopup: + { + const QStringList items = adjustedCompletionItems( false ); + setCompletedItems( items, false ); + } break; - } - QString match = s_static->completion->makeCompletion( m_searchString ); + case KGlobalSettings::CompletionShell: + { + const QString match = s_static->completion->makeCompletion( m_searchString ); + if ( !match.isNull() && match != m_searchString ) { + q->setText( m_previousAddresses + match ); + q->setModified( true ); + q->cursorAtEnd(); + } + } + break; + + case KGlobalSettings::CompletionMan: // Short-Auto in fact + case KGlobalSettings::CompletionAuto: + { + //force autoSuggest in KLineEdit::keyPressed or setCompletedText will have no effect + q->setCompletionMode( q->completionMode() ); + + if ( !m_searchString.isEmpty() ) { - if ( !match.isEmpty() ) { - if ( match != m_searchString ) { - QString adds = m_previousAddresses + match; - q->setCompletedText( adds ); - } - } else { - if ( !m_searchString.startsWith( QLatin1Char( '\"' ) ) ) { - //try with quoted text, if user has not type one already - match = s_static->completion->makeCompletion( QLatin1String( "\"" ) + m_searchString ); - if ( !match.isEmpty() && match != m_searchString ) { - m_searchString = QLatin1String( "\"" ) + m_searchString; - m_searchExtended = true; - q->setText( m_previousAddresses + m_searchString ); - q->setCompletedText( m_previousAddresses + match ); - } - } else if ( m_searchExtended ) { - //our added \" does not work anymore, remove it - m_searchString = m_searchString.mid( 1 ); - m_searchExtended = false; - q->setText( m_previousAddresses + m_searchString ); - //now try again - match = s_static->completion->makeCompletion( m_searchString ); - if ( !match.isEmpty() && match != m_searchString ) { - const QString adds = m_previousAddresses + match; - q->setCompletedText( adds ); - } - } - } - } - } - break; - - case KGlobalSettings::CompletionNone: - default: // fall through - break; - } + //if only our \" is left, remove it since user has not typed it either + if ( m_searchExtended && m_searchString == QLatin1String( "\"" ) ) { + m_searchExtended = false; + m_searchString.clear(); + q->setText( m_previousAddresses ); + break; + } + + QString match = s_static->completion->makeCompletion( m_searchString ); + + if ( !match.isEmpty() ) { + if ( match != m_searchString ) { + QString adds = m_previousAddresses + match; + q->setCompletedText( adds ); + } + } else { + if ( !m_searchString.startsWith( QLatin1Char( '\"' ) ) ) { + //try with quoted text, if user has not type one already + match = s_static->completion->makeCompletion( QLatin1String( "\"" ) + m_searchString ); + if ( !match.isEmpty() && match != m_searchString ) { + m_searchString = QLatin1String( "\"" ) + m_searchString; + m_searchExtended = true; + q->setText( m_previousAddresses + m_searchString ); + q->setCompletedText( m_previousAddresses + match ); + } + } else if ( m_searchExtended ) { + //our added \" does not work anymore, remove it + m_searchString = m_searchString.mid( 1 ); + m_searchExtended = false; + q->setText( m_previousAddresses + m_searchString ); + //now try again + match = s_static->completion->makeCompletion( m_searchString ); + if ( !match.isEmpty() && match != m_searchString ) { + const QString adds = m_previousAddresses + match; + q->setCompletedText( adds ); + } + } + } + } + } + break; + + case KGlobalSettings::CompletionNone: + default: // fall through + break; + } } void AddresseeLineEdit::Private::slotCompletion() { - // Called by KLineEdit's keyPressEvent for CompletionModes - // Auto,Popup -> new text, update search string. - // not called for CompletionShell, this is been taken care of - // in AddresseeLineEdit::keyPressEvent - - updateSearchString(); - if ( q->completionBox() ) { - q->completionBox()->setCancelledText( m_searchString ); - } + // Called by KLineEdit's keyPressEvent for CompletionModes + // Auto,Popup -> new text, update search string. + // not called for CompletionShell, this is been taken care of + // in AddresseeLineEdit::keyPressEvent + + updateSearchString(); + if ( q->completionBox() ) { + q->completionBox()->setCancelledText( m_searchString ); + } - startSearches(); - doCompletion( false ); + startSearches(); + doCompletion( false ); } void AddresseeLineEdit::Private::slotPopupCompletion( const QString &completion ) { - q->setText( m_previousAddresses + completion.trimmed() ); - q->cursorAtEnd(); - updateSearchString(); - q->emitTextCompleted(); + q->setText( m_previousAddresses + completion.trimmed() ); + q->cursorAtEnd(); + updateSearchString(); + q->emitTextCompleted(); } void AddresseeLineEdit::Private::slotReturnPressed( const QString & ) { - if ( !q->completionBox()->selectedItems().isEmpty() ) { - slotPopupCompletion( q->completionBox()->selectedItems().first()->text() ); - } + if ( !q->completionBox()->selectedItems().isEmpty() ) { + slotPopupCompletion( q->completionBox()->selectedItems().first()->text() ); + } } void AddresseeLineEdit::Private::slotStartLDAPLookup() { - if ( Solid::Networking::status() == Solid::Networking::Unconnected ) { - return; - } + if ( Solid::Networking::status() == Solid::Networking::Unconnected ) { + return; + } - const KGlobalSettings::Completion mode = q->completionMode(); + const KGlobalSettings::Completion mode = q->completionMode(); - if ( mode == KGlobalSettings::CompletionNone ) { - return; - } + if ( mode == KGlobalSettings::CompletionNone ) { + return; + } - if ( !s_static->ldapSearch->isAvailable() ) { - return; - } + if ( !s_static->ldapSearch->isAvailable() ) { + return; + } - if ( s_static->ldapLineEdit != q ) { - return; - } + if ( s_static->ldapLineEdit != q ) { + return; + } - startLoadingLDAPEntries(); + startLoadingLDAPEntries(); } void AddresseeLineEdit::Private::slotLDAPSearchData( const KLDAP::LdapResult::List &results ) { - if ( results.isEmpty() || s_static->ldapLineEdit != q ) { - return; - } - - foreach ( const KLDAP::LdapResult &result, results ) { - KABC::Addressee contact; - contact.setNameFromString( result.name ); - contact.setEmails( result.email ); - - if ( !s_static->ldapClientToCompletionSourceMap.contains( result.clientNumber ) ) { - s_static->updateLDAPWeights(); // we got results from a new source, so update the completion sources - } - - q->addContact( contact, result.completionWeight, - s_static->ldapClientToCompletionSourceMap[ result.clientNumber ] ); - } - - if ( ( q->hasFocus() || q->completionBox()->hasFocus() ) && - q->completionMode() != KGlobalSettings::CompletionNone && - q->completionMode() != KGlobalSettings::CompletionShell ) { - q->setText( m_previousAddresses + m_searchString ); - // only complete again if the user didn't change the selection while - // we were waiting; otherwise the completion box will be closed - const QListWidgetItem *current = q->completionBox()->currentItem(); - if ( !current || m_searchString.trimmed() != current->text().trimmed() ) { - doCompletion( m_lastSearchMode ); + if ( results.isEmpty() || s_static->ldapLineEdit != q ) { + return; + } + + foreach ( const KLDAP::LdapResult &result, results ) { + KABC::Addressee contact; + contact.setNameFromString( result.name ); + contact.setEmails( result.email ); + + if ( !s_static->ldapClientToCompletionSourceMap.contains( result.clientNumber ) ) { + s_static->updateLDAPWeights(); // we got results from a new source, so update the completion sources + } + + q->addContact( contact, result.completionWeight, + s_static->ldapClientToCompletionSourceMap[ result.clientNumber ] ); + } + + if ( ( q->hasFocus() || q->completionBox()->hasFocus() ) && + q->completionMode() != KGlobalSettings::CompletionNone && + q->completionMode() != KGlobalSettings::CompletionShell ) { + q->setText( m_previousAddresses + m_searchString ); + // only complete again if the user didn't change the selection while + // we were waiting; otherwise the completion box will be closed + const QListWidgetItem *current = q->completionBox()->currentItem(); + if ( !current || m_searchString.trimmed() != current->text().trimmed() ) { + doCompletion( m_lastSearchMode ); + } } - } } void AddresseeLineEdit::Private::slotEditCompletionOrder() { - init(); // for s_static->ldapSearch - if(m_useCompletion){ - s_static->slotEditCompletionOrder(); - } + init(); // for s_static->ldapSearch + if(m_useCompletion){ + s_static->slotEditCompletionOrder(); + } } void AddresseeLineEdit::Private::slotUserCancelled( const QString &cancelText ) { - if ( s_static->ldapSearch && s_static->ldapLineEdit == q ) { - stopLDAPLookup(); - } + if ( s_static->ldapSearch && s_static->ldapLineEdit == q ) { + stopLDAPLookup(); + } - q->userCancelled( m_previousAddresses + cancelText ); // in KLineEdit + q->userCancelled( m_previousAddresses + cancelText ); // in KLineEdit } void AddresseeLineEdit::Private::slotAkonadiHandleItems( const Akonadi::Item::List &items ) @@ -856,424 +883,424 @@ the source name can be correctly labeled.*/ foreach ( const Akonadi::Item &item, items ) { - // check the local cache of collections - const int sourceIndex = - s_static->akonadiCollectionToCompletionSourceMap.value( item.parentCollection().id(), -1 ); - if ( sourceIndex == -1 ) { - kDebug() << "Fetching New collection: " << item.parentCollection().id(); - // the collection isn't there, start the fetch job. - Akonadi::CollectionFetchJob *collectionJob = - new Akonadi::CollectionFetchJob( item.parentCollection(), - Akonadi::CollectionFetchJob::Base, - s_static->akonadiSession ); - connect( collectionJob, SIGNAL(collectionsReceived(Akonadi::Collection::List)), - q, SLOT(slotAkonadiCollectionsReceived(Akonadi::Collection::List)) ); - /* we don't want to start multiple fetch jobs for the same collection, + // check the local cache of collections + const int sourceIndex = + s_static->akonadiCollectionToCompletionSourceMap.value( item.parentCollection().id(), -1 ); + if ( sourceIndex == -1 ) { + kDebug() << "Fetching New collection: " << item.parentCollection().id(); + // the collection isn't there, start the fetch job. + Akonadi::CollectionFetchJob *collectionJob = + new Akonadi::CollectionFetchJob( item.parentCollection(), + Akonadi::CollectionFetchJob::Base, + s_static->akonadiSession ); + connect( collectionJob, SIGNAL(collectionsReceived(Akonadi::Collection::List)), + q, SLOT(slotAkonadiCollectionsReceived(Akonadi::Collection::List)) ); + /* we don't want to start multiple fetch jobs for the same collection, so insert the collection with an index value of -2 */ - s_static->akonadiCollectionToCompletionSourceMap.insert( item.parentCollection().id(), -2 ); - s_static->akonadiPendingItems.append( item ); - } else if ( sourceIndex == -2 ) { - /* fetch job already started, don't need to start another one, + s_static->akonadiCollectionToCompletionSourceMap.insert( item.parentCollection().id(), -2 ); + s_static->akonadiPendingItems.append( item ); + } else if ( sourceIndex == -2 ) { + /* fetch job already started, don't need to start another one, so just append the item as pending */ - s_static->akonadiPendingItems.append( item ); - } else { - q->addItem( item, 1, sourceIndex ); - } + s_static->akonadiPendingItems.append( item ); + } else { + q->addItem( item, 1, sourceIndex ); + } } - if ( !items.isEmpty() ) { - const QListWidgetItem *current = q->completionBox()->currentItem(); - if ( !current || m_searchString.trimmed() != current->text().trimmed() ) { - doCompletion( m_lastSearchMode ); - } + if ( !items.isEmpty() ) { + const QListWidgetItem *current = q->completionBox()->currentItem(); + if ( !current || m_searchString.trimmed() != current->text().trimmed() ) { + doCompletion( m_lastSearchMode ); + } } } void AddresseeLineEdit::Private::slotAkonadiSearchResult( KJob *job ) { - if ( job->error() ) { - kWarning() << "Akonadi search job failed: " << job->errorString(); - } else { - Akonadi::ItemSearchJob *searchJob = static_cast(job); - kDebug() << "Found" << searchJob->items().size() << "items"; - } - const int index = s_static->akonadiJobsInFlight.indexOf( qobject_cast( job ) ); - if( index != -1 ) - s_static->akonadiJobsInFlight.remove( index ); + if ( job->error() ) { + kWarning() << "Akonadi search job failed: " << job->errorString(); + } else { + Akonadi::ItemSearchJob *searchJob = static_cast(job); + kDebug() << "Found" << searchJob->items().size() << "items"; + } + const int index = s_static->akonadiJobsInFlight.indexOf( qobject_cast( job ) ); + if( index != -1 ) + s_static->akonadiJobsInFlight.remove( index ); } void AddresseeLineEdit::Private::slotAkonadiCollectionsReceived( - const Akonadi::Collection::List &collections ) + const Akonadi::Collection::List &collections ) { - foreach ( const Akonadi::Collection &collection, collections ) { - if ( collection.isValid() ) { - const QString sourceString = collection.displayName(); - const int index = q->addCompletionSource( sourceString, 1 ); - kDebug() << "\treceived: " << sourceString << "index: " << index; - s_static->akonadiCollectionToCompletionSourceMap.insert( collection.id(), index ); - } - } - - // now that we have added the new collections, recheck our list of pending contacts - akonadiHandlePending(); - // do completion - const QListWidgetItem *current = q->completionBox()->currentItem(); - if ( !current || m_searchString.trimmed() != current->text().trimmed() ) { - doCompletion( m_lastSearchMode ); - } + foreach ( const Akonadi::Collection &collection, collections ) { + if ( collection.isValid() ) { + const QString sourceString = collection.displayName(); + const int index = q->addCompletionSource( sourceString, 1 ); + kDebug() << "\treceived: " << sourceString << "index: " << index; + s_static->akonadiCollectionToCompletionSourceMap.insert( collection.id(), index ); + } + } + + // now that we have added the new collections, recheck our list of pending contacts + akonadiHandlePending(); + // do completion + const QListWidgetItem *current = q->completionBox()->currentItem(); + if ( !current || m_searchString.trimmed() != current->text().trimmed() ) { + doCompletion( m_lastSearchMode ); + } } // not cached, to make sure we get an up-to-date value when it changes KCompletion::CompOrder AddresseeLineEdit::Private::completionOrder() { - KConfig _config( QLatin1String( "kpimcompletionorder" ) ); - const KConfigGroup config( &_config, QLatin1String( "General" ) ); - const QString order = - config.readEntry( QLatin1String( "CompletionOrder" ), QString::fromLatin1( "Weighted" ) ); - - if ( order == QLatin1String( "Weighted" ) ) { - return KCompletion::Weighted; - } else { - return KCompletion::Sorted; - } + KConfig _config( QLatin1String( "kpimcompletionorder" ) ); + const KConfigGroup config( &_config, QLatin1String( "General" ) ); + const QString order = + config.readEntry( QLatin1String( "CompletionOrder" ), QString::fromLatin1( "Weighted" ) ); + + if ( order == QLatin1String( "Weighted" ) ) { + return KCompletion::Weighted; + } else { + return KCompletion::Sorted; + } } AddresseeLineEdit::AddresseeLineEdit( QWidget *parent, bool enableCompletion ) - : KLineEdit( parent ), d( new Private( this, enableCompletion ) ) + : KLineEdit( parent ), d( new Private( this, enableCompletion ) ) { - setObjectName( newLineEditObjectName() ); - setClickMessage( QString() ); + setObjectName( newLineEditObjectName() ); + setClickMessage( QString() ); - d->init(); + d->init(); } AddresseeLineEdit::~AddresseeLineEdit() { - if ( s_static->ldapSearch && s_static->ldapLineEdit == this ) { - d->stopLDAPLookup(); - } - delete d; + if ( s_static->ldapSearch && s_static->ldapLineEdit == this ) { + d->stopLDAPLookup(); + } + delete d; } void AddresseeLineEdit::setFont( const QFont &font ) { - KLineEdit::setFont( font ); + KLineEdit::setFont( font ); - if ( d->m_useCompletion ) { - completionBox()->setFont( font ); - } + if ( d->m_useCompletion ) { + completionBox()->setFont( font ); + } } void AddresseeLineEdit::allowSemicolonAsSeparator( bool useSemicolonAsSeparator ) { - d->m_useSemicolonAsSeparator = useSemicolonAsSeparator; + d->m_useSemicolonAsSeparator = useSemicolonAsSeparator; } void AddresseeLineEdit::keyPressEvent( QKeyEvent *event ) { - bool accept = false; + bool accept = false; - const int key = event->key() | event->modifiers(); + const int key = event->key() | event->modifiers(); - if ( KStandardShortcut::shortcut( KStandardShortcut::SubstringCompletion ).contains( key ) ) { - //TODO: add LDAP substring lookup, when it becomes available in KPIM::LDAPSearch - d->updateSearchString(); - d->startSearches(); - d->doCompletion( true ); - accept = true; - } else if ( KStandardShortcut::shortcut( KStandardShortcut::TextCompletion ).contains( key ) ) { - const int len = text().length(); - - if ( len == cursorPosition() ) { // at End? - d->updateSearchString(); - d->startSearches(); - d->doCompletion( true ); - accept = true; - } - } - - const QString oldContent = text(); - if ( !accept ) { - KLineEdit::keyPressEvent( event ); - } - - // if the text didn't change (eg. because a cursor navigation key was pressed) - // we don't need to trigger a new search - if ( oldContent == text() ) { - return; - } - - if ( event->isAccepted() ) { - d->updateSearchString(); - - QString searchString( d->m_searchString ); - //LDAP does not know about our string manipulation, remove it - if ( d->m_searchExtended ) { - searchString = d->m_searchString.mid( 1 ); + if ( KStandardShortcut::shortcut( KStandardShortcut::SubstringCompletion ).contains( key ) ) { + //TODO: add LDAP substring lookup, when it becomes available in KPIM::LDAPSearch + d->updateSearchString(); + d->startSearches(); + d->doCompletion( true ); + accept = true; + } else if ( KStandardShortcut::shortcut( KStandardShortcut::TextCompletion ).contains( key ) ) { + const int len = text().length(); + + if ( len == cursorPosition() ) { // at End? + d->updateSearchString(); + d->startSearches(); + d->doCompletion( true ); + accept = true; + } } - if ( d->m_useCompletion && s_static->ldapTimer ) { - if ( s_static->ldapText != searchString || s_static->ldapLineEdit != this ) { - d->stopLDAPLookup(); - } + const QString oldContent = text(); + if ( !accept ) { + KLineEdit::keyPressEvent( event ); + } - s_static->ldapText = searchString; - s_static->ldapLineEdit = this; - s_static->ldapTimer->setSingleShot( true ); - s_static->ldapTimer->start( 500 ); + // if the text didn't change (eg. because a cursor navigation key was pressed) + // we don't need to trigger a new search + if ( oldContent == text() ) { + return; + } + + if ( event->isAccepted() ) { + d->updateSearchString(); + + QString searchString( d->m_searchString ); + //LDAP does not know about our string manipulation, remove it + if ( d->m_searchExtended ) { + searchString = d->m_searchString.mid( 1 ); + } + + if ( d->m_useCompletion && s_static->ldapTimer ) { + if ( s_static->ldapText != searchString || s_static->ldapLineEdit != this ) { + d->stopLDAPLookup(); + } + + s_static->ldapText = searchString; + s_static->ldapLineEdit = this; + s_static->ldapTimer->setSingleShot( true ); + s_static->ldapTimer->start( 500 ); + } } - } } void AddresseeLineEdit::insert( const QString &t ) { - if ( !d->m_smartPaste ) { - KLineEdit::insert( t ); - return; - } - - QString newText = t.trimmed(); - if ( newText.isEmpty() ) { - return; - } - - // remove newlines in the to-be-pasted string - QStringList lines = newText.split( QRegExp( QLatin1String( "\r?\n" ) ), QString::SkipEmptyParts ); - QStringList::iterator end( lines.end() ); - for ( QStringList::iterator it = lines.begin(); it != end; ++it ) { - // remove trailing commas and whitespace - (*it).remove( QRegExp( QLatin1String( ",?\\s*$" ) ) ); - } - newText = lines.join( QLatin1String( ", " ) ); - - if ( newText.startsWith( QLatin1String( "mailto:" ) ) ) { - const KUrl url( newText ); - newText = url.path(); - } else if ( newText.indexOf( QLatin1String( " at " ) ) != -1 ) { - // Anti-spam stuff - newText.replace( QLatin1String( " at " ), QLatin1String( "@" ) ); - newText.replace( QLatin1String( " dot " ), QLatin1String( "." ) ); - } else if ( newText.indexOf( QLatin1String( "(at)" ) ) != -1 ) { - newText.replace( QRegExp( QLatin1String( "\\s*\\(at\\)\\s*" ) ), QLatin1String( "@" ) ); - } - - QString contents = text(); - int start_sel = 0; - int pos = cursorPosition(); - - if ( hasSelectedText() ) { - // Cut away the selection. - start_sel = selectionStart(); - pos = start_sel; - contents = contents.left( start_sel ) + contents.mid( start_sel + selectedText().length() ); - } - - int eot = contents.length(); - while ( ( eot > 0 ) && contents[ eot - 1 ].isSpace() ) { - eot--; - } - if ( eot == 0 ) { - contents.clear(); - } else if ( pos >= eot ) { - if ( contents[ eot - 1 ] == QLatin1Char( ',' ) ) { - eot--; - } - contents.truncate( eot ); - contents += QLatin1String( ", " ); - pos = eot + 2; - } - - contents = contents.left( pos ) + newText + contents.mid( pos ); - setText( contents ); - setModified( true ); - setCursorPosition( pos + newText.length() ); + if ( !d->m_smartPaste ) { + KLineEdit::insert( t ); + return; + } + + QString newText = t.trimmed(); + if ( newText.isEmpty() ) { + return; + } + + // remove newlines in the to-be-pasted string + QStringList lines = newText.split( QRegExp( QLatin1String( "\r?\n" ) ), QString::SkipEmptyParts ); + QStringList::iterator end( lines.end() ); + for ( QStringList::iterator it = lines.begin(); it != end; ++it ) { + // remove trailing commas and whitespace + (*it).remove( QRegExp( QLatin1String( ",?\\s*$" ) ) ); + } + newText = lines.join( QLatin1String( ", " ) ); + + if ( newText.startsWith( QLatin1String( "mailto:" ) ) ) { + const KUrl url( newText ); + newText = url.path(); + } else if ( newText.indexOf( QLatin1String( " at " ) ) != -1 ) { + // Anti-spam stuff + newText.replace( QLatin1String( " at " ), QLatin1String( "@" ) ); + newText.replace( QLatin1String( " dot " ), QLatin1String( "." ) ); + } else if ( newText.indexOf( QLatin1String( "(at)" ) ) != -1 ) { + newText.replace( QRegExp( QLatin1String( "\\s*\\(at\\)\\s*" ) ), QLatin1String( "@" ) ); + } + + QString contents = text(); + int start_sel = 0; + int pos = cursorPosition(); + + if ( hasSelectedText() ) { + // Cut away the selection. + start_sel = selectionStart(); + pos = start_sel; + contents = contents.left( start_sel ) + contents.mid( start_sel + selectedText().length() ); + } + + int eot = contents.length(); + while ( ( eot > 0 ) && contents.at( eot - 1 ).isSpace() ) { + --eot; + } + if ( eot == 0 ) { + contents.clear(); + } else if ( pos >= eot ) { + if ( contents.at( eot - 1 ) == QLatin1Char( ',' ) ) { + --eot; + } + contents.truncate( eot ); + contents += QLatin1String( ", " ); + pos = eot + 2; + } + + contents = contents.left( pos ) + newText + contents.mid( pos ); + setText( contents ); + setModified( true ); + setCursorPosition( pos + newText.length() ); } void AddresseeLineEdit::setText( const QString & text ) { - const int cursorPos = cursorPosition(); - KLineEdit::setText( text.trimmed() ); - setCursorPosition( cursorPos ); + const int cursorPos = cursorPosition(); + KLineEdit::setText( text.trimmed() ); + setCursorPosition( cursorPos ); } void AddresseeLineEdit::paste() { - if ( d->m_useCompletion ) { - d->m_smartPaste = true; - } + if ( d->m_useCompletion ) { + d->m_smartPaste = true; + } - KLineEdit::paste(); - d->m_smartPaste = false; + KLineEdit::paste(); + d->m_smartPaste = false; } void AddresseeLineEdit::mouseReleaseEvent( QMouseEvent *event ) { - // reimplemented from QLineEdit::mouseReleaseEvent() + // reimplemented from QLineEdit::mouseReleaseEvent() #ifndef QT_NO_CLIPBOARD - if ( d->m_useCompletion && - QApplication::clipboard()->supportsSelection() && - !isReadOnly() && - event->button() == Qt::MidButton ) { - d->m_smartPaste = true; - } + if ( d->m_useCompletion && + QApplication::clipboard()->supportsSelection() && + !isReadOnly() && + event->button() == Qt::MidButton ) { + d->m_smartPaste = true; + } #endif - KLineEdit::mouseReleaseEvent( event ); - d->m_smartPaste = false; + KLineEdit::mouseReleaseEvent( event ); + d->m_smartPaste = false; } #ifndef QT_NO_DRAGANDDROP void AddresseeLineEdit::dropEvent( QDropEvent *event ) { - if ( !isReadOnly() ) { - const KUrl::List uriList = KUrl::List::fromMimeData( event->mimeData() ); - if ( !uriList.isEmpty() ) { - QString contents = text(); - // remove trailing white space and comma - int eot = contents.length(); - while ( ( eot > 0 ) && contents[ eot - 1 ].isSpace() ) { - eot--; - } - if ( eot == 0 ) { - contents.clear(); - } else if ( contents[ eot - 1 ] == QLatin1Char(',') ) { - eot--; - contents.truncate( eot ); - } - bool mailtoURL = false; - // append the mailto URLs - foreach ( const KUrl &url, uriList ) { - if ( url.protocol() == QLatin1String( "mailto" ) ) { - mailtoURL = true; - QString address; - address = KUrl::fromPercentEncoding( url.path().toLatin1() ); - address = KMime::decodeRFC2047String( address.toLatin1() ); - if ( !contents.isEmpty() ) { - contents.append( QLatin1String( ", " ) ); - } - contents.append( address ); - } - } - if ( mailtoURL ) { - setText( contents ); - setModified( true ); - return; - } - } else { - // Let's see if this drop contains a comma separated list of emails - const QString dropData = QString::fromUtf8( event->encodedData( "text/plain" ) ); - const QStringList addrs = KPIMUtils::splitAddressList( dropData ); - if ( !addrs.isEmpty() ) { - setText( KPIMUtils::normalizeAddressesAndDecodeIdn( dropData ) ); - setModified( true ); - return; - } + if ( !isReadOnly() ) { + const KUrl::List uriList = KUrl::List::fromMimeData( event->mimeData() ); + if ( !uriList.isEmpty() ) { + QString contents = text(); + // remove trailing white space and comma + int eot = contents.length(); + while ( ( eot > 0 ) && contents.at( eot - 1 ).isSpace() ) { + --eot; + } + if ( eot == 0 ) { + contents.clear(); + } else if ( contents.at( eot - 1 ) == QLatin1Char(',') ) { + --eot; + contents.truncate( eot ); + } + bool mailtoURL = false; + // append the mailto URLs + foreach ( const KUrl &url, uriList ) { + if ( url.protocol() == QLatin1String( "mailto" ) ) { + mailtoURL = true; + QString address; + address = KUrl::fromPercentEncoding( url.path().toLatin1() ); + address = KMime::decodeRFC2047String( address.toLatin1() ); + if ( !contents.isEmpty() ) { + contents.append( QLatin1String( ", " ) ); + } + contents.append( address ); + } + } + if ( mailtoURL ) { + setText( contents ); + setModified( true ); + return; + } + } else { + // Let's see if this drop contains a comma separated list of emails + const QString dropData = QString::fromUtf8( event->encodedData( "text/plain" ) ); + const QStringList addrs = KPIMUtils::splitAddressList( dropData ); + if ( !addrs.isEmpty() ) { + setText( KPIMUtils::normalizeAddressesAndDecodeIdn( dropData ) ); + setModified( true ); + return; + } + } } - } - if ( d->m_useCompletion ) { - d->m_smartPaste = true; - } + if ( d->m_useCompletion ) { + d->m_smartPaste = true; + } - QLineEdit::dropEvent( event ); - d->m_smartPaste = false; + QLineEdit::dropEvent( event ); + d->m_smartPaste = false; } #endif // QT_NO_DRAGANDDROP void AddresseeLineEdit::cursorAtEnd() { - setCursorPosition( text().length() ); + setCursorPosition( text().length() ); } void AddresseeLineEdit::enableCompletion( bool enable ) { - d->m_useCompletion = enable; + d->m_useCompletion = enable; } void AddresseeLineEdit::addItem( const Akonadi::Item &item, int weight, int source ) { - //Let Akonadi results always have a higher weight than baloo results - if ( item.hasPayload() ) { - addContact( item.payload(), weight + 1, source ); - } else if ( item.hasPayload() ) { - addContactGroup( item.payload(), weight + 1, source ); - } + //Let Akonadi results always have a higher weight than baloo results + if ( item.hasPayload() ) { + addContact( item.payload(), weight + 1, source ); + } else if ( item.hasPayload() ) { + addContactGroup( item.payload(), weight + 1, source ); + } } void AddresseeLineEdit::addContactGroup( const KABC::ContactGroup &group, int weight, int source ) { - d->addCompletionItem( group.name(), weight, source ); + d->addCompletionItem( group.name(), weight, source ); } void AddresseeLineEdit::addContact( const KABC::Addressee &addr, int weight, int source ) { - const QStringList emails = addr.emails(); - QStringList::ConstIterator it; - int isPrefEmail = 1; //first in list is preferredEmail - QStringList::ConstIterator end( emails.constEnd() ); - for ( it = emails.constBegin(); it != end; ++it ) { - //TODO: highlight preferredEmail - const QString email( (*it) ); - const QString givenName = addr.givenName(); - const QString familyName= addr.familyName(); - const QString nickName = addr.nickName(); - QString fullEmail = addr.fullEmail( email ); - - // Prepare "givenName" + ' ' + "familyName" - QString fullName = givenName; - if (!familyName.isEmpty()) { - if (!fullName.isEmpty()) - fullName += QLatin1Char(' '); - fullName += familyName; - } - - // Finally, we can add the completion items - if (!fullName.isEmpty()) { - const QString address = KPIMUtils::normalizedAddress(fullName, email, QString()); - if (fullEmail != address) { - // This happens when fullEmail contains a middle name, while our own fullName+email only has "first last". - // Let's offer both, the fullEmail with 3 parts, looks a tad formal. - d->addCompletionItem(address, weight + isPrefEmail, source); - } - } - - QStringList keyWords; - if (!nickName.isEmpty()) { - keyWords.append(nickName); - } + const QStringList emails = addr.emails(); + QStringList::ConstIterator it; + int isPrefEmail = 1; //first in list is preferredEmail + QStringList::ConstIterator end( emails.constEnd() ); + for ( it = emails.constBegin(); it != end; ++it ) { + //TODO: highlight preferredEmail + const QString email( (*it) ); + const QString givenName = addr.givenName(); + const QString familyName= addr.familyName(); + const QString nickName = addr.nickName(); + QString fullEmail = addr.fullEmail( email ); + + // Prepare "givenName" + ' ' + "familyName" + QString fullName = givenName; + if (!familyName.isEmpty()) { + if (!fullName.isEmpty()) + fullName += QLatin1Char(' '); + fullName += familyName; + } + + // Finally, we can add the completion items + if (!fullName.isEmpty()) { + const QString address = KPIMUtils::normalizedAddress(fullName, email, QString()); + if (fullEmail != address) { + // This happens when fullEmail contains a middle name, while our own fullName+email only has "first last". + // Let's offer both, the fullEmail with 3 parts, looks a tad formal. + d->addCompletionItem(address, weight + isPrefEmail, source); + } + } + + QStringList keyWords; + if (!nickName.isEmpty()) { + keyWords.append(nickName); + } - d->addCompletionItem( fullEmail, weight + isPrefEmail, source, &keyWords ); + d->addCompletionItem( fullEmail, weight + isPrefEmail, source, &keyWords ); - isPrefEmail = 0; - } + isPrefEmail = 0; + } } #ifndef QT_NO_CONTEXTMENU void AddresseeLineEdit::contextMenuEvent( QContextMenuEvent *event ) { - QMenu *menu = createStandardContextMenu(); - if ( menu ) { // can be 0 on platforms with only a touch interface - menu->exec( event->globalPos() ); - delete menu; - } + QMenu *menu = createStandardContextMenu(); + if ( menu ) { // can be 0 on platforms with only a touch interface + menu->exec( event->globalPos() ); + delete menu; + } } QMenu *AddresseeLineEdit::createStandardContextMenu() { - // disable modes not supported by KMailCompletion - setCompletionModeDisabled( KGlobalSettings::CompletionMan ); - setCompletionModeDisabled( KGlobalSettings::CompletionPopupAuto ); - - QMenu *menu = KLineEdit::createStandardContextMenu(); - if ( !menu ) { - return 0; - } - - if ( d->m_useCompletion ) { - menu->addAction( i18n( "Configure Completion Order..." ), - this, SLOT(slotEditCompletionOrder()) ); - } - return menu; + // disable modes not supported by KMailCompletion + setCompletionModeDisabled( KGlobalSettings::CompletionMan ); + setCompletionModeDisabled( KGlobalSettings::CompletionPopupAuto ); + + QMenu *menu = KLineEdit::createStandardContextMenu(); + if ( !menu ) { + return 0; + } + + if ( d->m_useCompletion ) { + menu->addAction( i18n( "Configure Completion Order..." ), + this, SLOT(slotEditCompletionOrder()) ); + } + return menu; } #endif @@ -1289,175 +1316,175 @@ bool KPIM::AddresseeLineEdit::eventFilter( QObject *object, QEvent *event ) { - if ( d->m_completionInitialized && - ( object == completionBox() || - completionBox()->findChild( object->objectName() ) == object ) ) { - if ( event->type() == QEvent::MouseButtonPress || - event->type() == QEvent::MouseMove || - event->type() == QEvent::MouseButtonRelease || - event->type() == QEvent::MouseButtonDblClick ) { - - const QMouseEvent* mouseEvent = static_cast( event ); - // find list box item at the event position - QListWidgetItem *item = completionBox()->itemAt( mouseEvent->pos() ); - if ( !item ) { - // In the case of a mouse move outside of the box we don't want - // the parent to fuzzy select a header by mistake. - bool eat = event->type() == QEvent::MouseMove; - return eat; - } - // avoid selection of headers on button press, or move or release while - // a button is pressed - const Qt::MouseButtons buttons = mouseEvent->buttons(); - if ( event->type() == QEvent::MouseButtonPress || - event->type() == QEvent::MouseButtonDblClick || - buttons & Qt::LeftButton || buttons & Qt::MidButton || - buttons & Qt::RightButton ) { - if ( itemIsHeader( item ) ) { - return true; // eat the event, we don't want anything to happen - } else { - // if we are not on one of the group heading, make sure the item - // below or above is selected, not the heading, inadvertedly, due - // to fuzzy auto-selection from QListBox - completionBox()->setCurrentItem( item ); - item->setSelected( true ); - if ( event->type() == QEvent::MouseMove ) { - return true; // avoid fuzzy selection behavior - } - } - } - } - } - - if ( ( object == this ) && - ( event->type() == QEvent::ShortcutOverride ) ) { - QKeyEvent *keyEvent = static_cast( event ); - if ( keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down || - keyEvent->key() == Qt::Key_Tab ) { - keyEvent->accept(); - return true; - } - } - - if ( ( object == this ) && - ( event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease ) && - completionBox()->isVisible() ) { - const QKeyEvent *keyEvent = static_cast( event ); - int currentIndex = completionBox()->currentRow(); - if ( currentIndex < 0 ) { - return true; - } - if ( keyEvent->key() == Qt::Key_Up ) { - //kDebug() <<"EVENTFILTER: Qt::Key_Up currentIndex=" << currentIndex; - // figure out if the item we would be moving to is one we want - // to ignore. If so, go one further - const QListWidgetItem *itemAbove = completionBox()->item( currentIndex ); - if ( itemAbove && itemIsHeader( itemAbove ) ) { - // there is a header above is, check if there is even further up - // and if so go one up, so it'll be selected - if ( currentIndex > 0 && completionBox()->item( currentIndex - 1 ) ) { - //kDebug() <<"EVENTFILTER: Qt::Key_Up -> skipping" << currentIndex - 1; - completionBox()->setCurrentRow( currentIndex - 1 ); - completionBox()->item( currentIndex - 1 )->setSelected( true ); - } else if ( currentIndex == 0 ) { - // nothing to skip to, let's stay where we are, but make sure the - // first header becomes visible, if we are the first real entry - completionBox()->scrollToItem( completionBox()->item( 0 ) ); - QListWidgetItem *item = completionBox()->item( currentIndex ); - if ( item ) { - if ( itemIsHeader( item ) ) { - currentIndex++; - item = completionBox()->item( currentIndex ); + if ( d->m_completionInitialized && + ( object == completionBox() || + completionBox()->findChild( object->objectName() ) == object ) ) { + if ( event->type() == QEvent::MouseButtonPress || + event->type() == QEvent::MouseMove || + event->type() == QEvent::MouseButtonRelease || + event->type() == QEvent::MouseButtonDblClick ) { + + const QMouseEvent* mouseEvent = static_cast( event ); + // find list box item at the event position + QListWidgetItem *item = completionBox()->itemAt( mouseEvent->pos() ); + if ( !item ) { + // In the case of a mouse move outside of the box we don't want + // the parent to fuzzy select a header by mistake. + bool eat = event->type() == QEvent::MouseMove; + return eat; + } + // avoid selection of headers on button press, or move or release while + // a button is pressed + const Qt::MouseButtons buttons = mouseEvent->buttons(); + if ( event->type() == QEvent::MouseButtonPress || + event->type() == QEvent::MouseButtonDblClick || + buttons & Qt::LeftButton || buttons & Qt::MidButton || + buttons & Qt::RightButton ) { + if ( itemIsHeader( item ) ) { + return true; // eat the event, we don't want anything to happen + } else { + // if we are not on one of the group heading, make sure the item + // below or above is selected, not the heading, inadvertedly, due + // to fuzzy auto-selection from QListBox + completionBox()->setCurrentItem( item ); + item->setSelected( true ); + if ( event->type() == QEvent::MouseMove ) { + return true; // avoid fuzzy selection behavior + } + } } - completionBox()->setCurrentItem( item ); - item->setSelected( true ); - } } + } - return true; - } - } else if ( keyEvent->key() == Qt::Key_Down ) { - // same strategy for downwards - //kDebug() <<"EVENTFILTER: Qt::Key_Down. currentIndex=" << currentIndex; - const QListWidgetItem *itemBelow = completionBox()->item( currentIndex ); - if ( itemBelow && itemIsHeader( itemBelow ) ) { - if ( completionBox()->item( currentIndex + 1 ) ) { - //kDebug() <<"EVENTFILTER: Qt::Key_Down -> skipping" << currentIndex+1; - completionBox()->setCurrentRow( currentIndex + 1 ); - completionBox()->item( currentIndex + 1 )->setSelected( true ); - } else { - // nothing to skip to, let's stay where we are - QListWidgetItem *item = completionBox()->item( currentIndex ); - if ( item ) { - completionBox()->setCurrentItem( item ); - item->setSelected( true ); - } + if ( ( object == this ) && + ( event->type() == QEvent::ShortcutOverride ) ) { + QKeyEvent *keyEvent = static_cast( event ); + if ( keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down || + keyEvent->key() == Qt::Key_Tab ) { + keyEvent->accept(); + return true; } + } - return true; - } - // special case of the initial selection, which is unfortunately a header. - // Setting it to selected tricks KCompletionBox into not treating is special - // and selecting making it current, instead of the one below. - QListWidgetItem *item = completionBox()->item( currentIndex ); - if ( item && itemIsHeader( item ) ) { - completionBox()->setCurrentItem( item ); - item->setSelected( true ); - } - } else if ( event->type() == QEvent::KeyRelease && - ( keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab ) ) { - /// first, find the header of the current section - QListWidgetItem *myHeader = 0; - int myHeaderIndex = -1; - const int iterationStep = keyEvent->key() == Qt::Key_Tab ? 1 : -1; - int index = qMin( qMax( currentIndex - iterationStep, 0 ), completionBox()->count() - 1 ); - while ( index >= 0 ) { - if ( itemIsHeader( completionBox()->item( index ) ) ) { - myHeader = completionBox()->item( index ); - myHeaderIndex = index; - break; - } - - index--; - } - Q_ASSERT( myHeader ); // we should always be able to find a header - - // find the next header (searching backwards, for Qt::Key_Backtab) - QListWidgetItem *nextHeader = 0; - - // when iterating forward, start at the currentindex, when backwards, - // one up from our header, or at the end - uint j; - if ( keyEvent->key() == Qt::Key_Tab ) { - j = currentIndex; - } else { - index = myHeaderIndex; - if ( index == 0 ) { - j = completionBox()->count() - 1; - } else { - j = ( index - 1 ) % completionBox()->count(); + if ( ( object == this ) && + ( event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease ) && + completionBox()->isVisible() ) { + const QKeyEvent *keyEvent = static_cast( event ); + int currentIndex = completionBox()->currentRow(); + if ( currentIndex < 0 ) { + return true; } - } - while ( ( nextHeader = completionBox()->item( j ) ) && nextHeader != myHeader ) { - if ( itemIsHeader( nextHeader ) ) { - break; - } - j = ( j + iterationStep ) % completionBox()->count(); - } + if ( keyEvent->key() == Qt::Key_Up ) { + //kDebug() <<"EVENTFILTER: Qt::Key_Up currentIndex=" << currentIndex; + // figure out if the item we would be moving to is one we want + // to ignore. If so, go one further + const QListWidgetItem *itemAbove = completionBox()->item( currentIndex ); + if ( itemAbove && itemIsHeader( itemAbove ) ) { + // there is a header above is, check if there is even further up + // and if so go one up, so it'll be selected + if ( currentIndex > 0 && completionBox()->item( currentIndex - 1 ) ) { + //kDebug() <<"EVENTFILTER: Qt::Key_Up -> skipping" << currentIndex - 1; + completionBox()->setCurrentRow( currentIndex - 1 ); + completionBox()->item( currentIndex - 1 )->setSelected( true ); + } else if ( currentIndex == 0 ) { + // nothing to skip to, let's stay where we are, but make sure the + // first header becomes visible, if we are the first real entry + completionBox()->scrollToItem( completionBox()->item( 0 ) ); + QListWidgetItem *item = completionBox()->item( currentIndex ); + if ( item ) { + if ( itemIsHeader( item ) ) { + currentIndex++; + item = completionBox()->item( currentIndex ); + } + completionBox()->setCurrentItem( item ); + item->setSelected( true ); + } + } - if ( nextHeader && nextHeader != myHeader ) { - QListWidgetItem *item = completionBox()->item( j + 1 ); - if ( item && !itemIsHeader( item ) ) { - completionBox()->setCurrentItem( item ); - item->setSelected( true ); - } - } + return true; + } + } else if ( keyEvent->key() == Qt::Key_Down ) { + // same strategy for downwards + //kDebug() <<"EVENTFILTER: Qt::Key_Down. currentIndex=" << currentIndex; + const QListWidgetItem *itemBelow = completionBox()->item( currentIndex ); + if ( itemBelow && itemIsHeader( itemBelow ) ) { + if ( completionBox()->item( currentIndex + 1 ) ) { + //kDebug() <<"EVENTFILTER: Qt::Key_Down -> skipping" << currentIndex+1; + completionBox()->setCurrentRow( currentIndex + 1 ); + completionBox()->item( currentIndex + 1 )->setSelected( true ); + } else { + // nothing to skip to, let's stay where we are + QListWidgetItem *item = completionBox()->item( currentIndex ); + if ( item ) { + completionBox()->setCurrentItem( item ); + item->setSelected( true ); + } + } + + return true; + } + // special case of the initial selection, which is unfortunately a header. + // Setting it to selected tricks KCompletionBox into not treating is special + // and selecting making it current, instead of the one below. + QListWidgetItem *item = completionBox()->item( currentIndex ); + if ( item && itemIsHeader( item ) ) { + completionBox()->setCurrentItem( item ); + item->setSelected( true ); + } + } else if ( event->type() == QEvent::KeyRelease && + ( keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab ) ) { + /// first, find the header of the current section + QListWidgetItem *myHeader = 0; + int myHeaderIndex = -1; + const int iterationStep = keyEvent->key() == Qt::Key_Tab ? 1 : -1; + int index = qMin( qMax( currentIndex - iterationStep, 0 ), completionBox()->count() - 1 ); + while ( index >= 0 ) { + if ( itemIsHeader( completionBox()->item( index ) ) ) { + myHeader = completionBox()->item( index ); + myHeaderIndex = index; + break; + } + + index--; + } + Q_ASSERT( myHeader ); // we should always be able to find a header - return true; + // find the next header (searching backwards, for Qt::Key_Backtab) + QListWidgetItem *nextHeader = 0; + + // when iterating forward, start at the currentindex, when backwards, + // one up from our header, or at the end + uint j; + if ( keyEvent->key() == Qt::Key_Tab ) { + j = currentIndex; + } else { + index = myHeaderIndex; + if ( index == 0 ) { + j = completionBox()->count() - 1; + } else { + j = ( index - 1 ) % completionBox()->count(); + } + } + while ( ( nextHeader = completionBox()->item( j ) ) && nextHeader != myHeader ) { + if ( itemIsHeader( nextHeader ) ) { + break; + } + j = ( j + iterationStep ) % completionBox()->count(); + } + + if ( nextHeader && nextHeader != myHeader ) { + QListWidgetItem *item = completionBox()->item( j + 1 ); + if ( item && !itemIsHeader( item ) ) { + completionBox()->setCurrentItem( item ); + item->setSelected( true ); + } + } + + return true; + } } - } - return KLineEdit::eventFilter( object, event ); + return KLineEdit::eventFilter( object, event ); } void AddresseeLineEdit::emitTextCompleted() diff -Nru kdepim-4.12.97/libkdepim/addressline/addresseelineedit.h kdepim-4.13.0/libkdepim/addressline/addresseelineedit.h --- kdepim-4.12.97/libkdepim/addressline/addresseelineedit.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/addressline/addresseelineedit.h 2014-04-10 07:40:20.000000000 +0000 @@ -41,12 +41,12 @@ class QObject; namespace Akonadi { - class Item; +class Item; } namespace KABC { - class Addressee; - class ContactGroup; +class Addressee; +class ContactGroup; } namespace KPIM { @@ -54,9 +54,9 @@ class KDEPIM_EXPORT AddresseeLineEdit : public KLineEdit { - Q_OBJECT + Q_OBJECT - public: +public: /** * Creates a new addressee line edit. * @@ -79,10 +79,10 @@ * Reimplemented for setting the @p font for line edit and completion box. */ void setFont( const QFont &font ); - Q_SIGNALS: +Q_SIGNALS: void textCompleted(); - public Q_SLOTS: +public Q_SLOTS: /** * Moves the cursor at the end of the line edit. */ @@ -99,7 +99,7 @@ */ virtual void setText( const QString &text ); - protected: +protected: /** * Adds a new @p contact to the completion with a given @p weight and @p source index. */ @@ -169,7 +169,7 @@ virtual void contextMenuEvent( QContextMenuEvent * ); #endif - private: +private: virtual bool eventFilter( QObject *, QEvent * ); void emitTextCompleted(); diff -Nru kdepim-4.12.97/libkdepim/addressline/completionordereditor.cpp kdepim-4.13.0/libkdepim/addressline/completionordereditor.cpp --- kdepim-4.12.97/libkdepim/addressline/completionordereditor.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/addressline/completionordereditor.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -59,97 +59,98 @@ using namespace KPIM; CompletionOrderEditorAdaptor::CompletionOrderEditorAdaptor( QObject *parent ) - : QDBusAbstractAdaptor( parent ) + : QDBusAbstractAdaptor( parent ) { - setAutoRelaySignals( true ); + setAutoRelaySignals( true ); } class LDAPCompletionItem : public CompletionItem { - public: +public: LDAPCompletionItem( KLDAP::LdapClient *ldapClient ) - : mLdapClient( ldapClient ), mWeight(0) + : mLdapClient( ldapClient ) { + mWeight = mLdapClient->completionWeight(); } virtual QString label() const { - return i18n( "LDAP server %1", mLdapClient->server().host() ); + return i18n( "LDAP server %1", mLdapClient->server().host() ); } virtual QIcon icon() const { - return KIcon( QLatin1String("view-ldap-resource") ); + return KIcon( QLatin1String("view-ldap-resource") ); } virtual int completionWeight() const { - return mLdapClient->completionWeight(); + return mWeight; } virtual void save( CompletionOrderEditor* ) { - KConfig *config = KLDAP::LdapClientSearchConfig::config(); - KConfigGroup group( config, "LDAP" ); - group.writeEntry( QString::fromLatin1("SelectedCompletionWeight%1" ).arg( mLdapClient->clientNumber() ), - mWeight ); - group.sync(); + KConfig *config = KLDAP::LdapClientSearchConfig::config(); + KConfigGroup group( config, "LDAP" ); + group.writeEntry( QString::fromLatin1("SelectedCompletionWeight%1" ).arg( mLdapClient->clientNumber() ), + mWeight ); + group.sync(); } - protected: +protected: virtual void setCompletionWeight( int weight ) { - mWeight = weight; + mWeight = weight; } - private: +private: KLDAP::LdapClient *mLdapClient; int mWeight; }; class SimpleCompletionItem : public CompletionItem { - public: +public: SimpleCompletionItem( CompletionOrderEditor* editor, const QString& label, const QString& identifier, int weight ) - : mLabel( label ), mIdentifier( identifier ) + : mLabel( label ), mIdentifier( identifier ) { - KConfigGroup group( editor->configFile(), "CompletionWeights" ); - mWeight = group.readEntry( mIdentifier, weight ); + KConfigGroup group( editor->configFile(), "CompletionWeights" ); + mWeight = group.readEntry( mIdentifier, weight ); } void setIcon( const QIcon &icon ) { - mIcon = icon; + mIcon = icon; } virtual QString label() const { - return mLabel; + return mLabel; } virtual QIcon icon() const { - return mIcon; + return mIcon; } virtual int completionWeight() const { - return mWeight; + return mWeight; } virtual void save( CompletionOrderEditor *editor ) { - KConfigGroup group( editor->configFile(), "CompletionWeights" ); - group.writeEntry( mIdentifier, mWeight ); + KConfigGroup group( editor->configFile(), "CompletionWeights" ); + group.writeEntry( mIdentifier, mWeight ); } - protected: +protected: virtual void setCompletionWeight( int weight ) { - mWeight = weight; + mWeight = weight; } - private: +private: QString mLabel; QString mIdentifier; int mWeight; @@ -160,87 +161,87 @@ class CompletionViewItem : public QTreeWidgetItem { - public: +public: CompletionViewItem( QTreeWidget *parent, CompletionItem* item, QTreeWidgetItem *preceding ) - : QTreeWidgetItem( parent, preceding ) + : QTreeWidgetItem( parent, preceding ) { - setItem( item ); + setItem( item ); } void setItem( CompletionItem *item ) { - mItem = item; - setText( 0, mItem->label() ); - setIcon( 0, mItem->icon() ); + mItem = item; + setText( 0, mItem->label() ); + setIcon( 0, mItem->icon() ); } CompletionItem* item() const { - return mItem; + return mItem; } bool operator<( const QTreeWidgetItem &other ) const { - const QTreeWidgetItem *otherItem = &other; - const CompletionViewItem *completionItem = static_cast( otherItem ); - // item with weight 100 should be on the top -> reverse sorting - return (mItem->completionWeight() > completionItem->item()->completionWeight()); + const QTreeWidgetItem *otherItem = &other; + const CompletionViewItem *completionItem = static_cast( otherItem ); + // item with weight 100 should be on the top -> reverse sorting + return (mItem->completionWeight() > completionItem->item()->completionWeight()); } - private: +private: CompletionItem* mItem; }; CompletionOrderEditor::CompletionOrderEditor( KLDAP::LdapClientSearch* ldapSearch, QWidget* parent ) - : KDialog( parent ), mConfig( QLatin1String("kpimcompletionorder") ), mLdapSearch( ldapSearch ), mDirty( false ) + : KDialog( parent ), mConfig( QLatin1String("kpimcompletionorder") ), mLdapSearch( ldapSearch ), mDirty( false ) { - setCaption( i18n( "Edit Completion Order" ) ); - setButtons( Ok|Cancel ); - setDefaultButton( Ok ); - setModal( true ); - showButtonSeparator( true ); - new CompletionOrderEditorAdaptor( this ); - QDBusConnection::sessionBus().registerObject( QLatin1String("/"), this, QDBusConnection::ExportAdaptors ); - - KHBox* page = new KHBox( this ); - setMainWidget( page ); - mListView = new QTreeWidget( page ); - mListView->setColumnCount( 1 ); - mListView->setAlternatingRowColors( true ); - mListView->setIndentation( 0 ); - mListView->setAllColumnsShowFocus( true ); - mListView->setHeaderHidden ( true ); - mListView->setSortingEnabled( true ); - - KVBox* upDownBox = new KVBox( page ); - mUpButton = new KPushButton( upDownBox ); - mUpButton->setAutoRepeat(true); - mUpButton->setObjectName( QLatin1String("mUpButton") ); - mUpButton->setIcon( KIcon(QLatin1String("go-up")) ); - mUpButton->setEnabled( false ); // b/c no item is selected yet - mUpButton->setFocusPolicy( Qt::StrongFocus ); - - mDownButton = new KPushButton( upDownBox ); - mDownButton->setAutoRepeat(true); - mDownButton->setObjectName( QLatin1String("mDownButton") ); - mDownButton->setIcon( KIcon(QLatin1String("go-down")) ); - mDownButton->setEnabled( false ); // b/c no item is selected yet - mDownButton->setFocusPolicy( Qt::StrongFocus ); - - QWidget* spacer = new QWidget( upDownBox ); - upDownBox->setStretchFactor( spacer, 100 ); - - connect( mListView, SIGNAL(itemSelectionChanged()), - SLOT(slotSelectionChanged()) ); - connect( mListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), - SLOT(slotSelectionChanged()) ); - connect( mUpButton, SIGNAL(clicked()), this, SLOT(slotMoveUp()) ); - connect( mDownButton, SIGNAL(clicked()), this, SLOT(slotMoveDown()) ); - connect( this, SIGNAL(okClicked()), this, SLOT(slotOk())); + setCaption( i18n( "Edit Completion Order" ) ); + setButtons( Ok|Cancel ); + setDefaultButton( Ok ); + setModal( true ); + showButtonSeparator( true ); + new CompletionOrderEditorAdaptor( this ); + QDBusConnection::sessionBus().registerObject( QLatin1String("/"), this, QDBusConnection::ExportAdaptors ); + + KHBox* page = new KHBox( this ); + setMainWidget( page ); + mListView = new QTreeWidget( page ); + mListView->setColumnCount( 1 ); + mListView->setAlternatingRowColors( true ); + mListView->setIndentation( 0 ); + mListView->setAllColumnsShowFocus( true ); + mListView->setHeaderHidden ( true ); + mListView->setSortingEnabled( true ); + + KVBox* upDownBox = new KVBox( page ); + mUpButton = new KPushButton( upDownBox ); + mUpButton->setAutoRepeat(true); + mUpButton->setObjectName( QLatin1String("mUpButton") ); + mUpButton->setIcon( KIcon(QLatin1String("go-up")) ); + mUpButton->setEnabled( false ); // b/c no item is selected yet + mUpButton->setFocusPolicy( Qt::StrongFocus ); + + mDownButton = new KPushButton( upDownBox ); + mDownButton->setAutoRepeat(true); + mDownButton->setObjectName( QLatin1String("mDownButton") ); + mDownButton->setIcon( KIcon(QLatin1String("go-down")) ); + mDownButton->setEnabled( false ); // b/c no item is selected yet + mDownButton->setFocusPolicy( Qt::StrongFocus ); + + QWidget* spacer = new QWidget( upDownBox ); + upDownBox->setStretchFactor( spacer, 100 ); + + connect( mListView, SIGNAL(itemSelectionChanged()), + SLOT(slotSelectionChanged()) ); + connect( mListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), + SLOT(slotSelectionChanged()) ); + connect( mUpButton, SIGNAL(clicked()), this, SLOT(slotMoveUp()) ); + connect( mDownButton, SIGNAL(clicked()), this, SLOT(slotMoveDown()) ); + connect( this, SIGNAL(okClicked()), this, SLOT(slotOk())); - loadCompletionItems(); - readConfig(); + loadCompletionItems(); + readConfig(); } CompletionOrderEditor::~CompletionOrderEditor() @@ -267,120 +268,120 @@ void CompletionOrderEditor::addCompletionItemForIndex( const QModelIndex &index ) { - const Akonadi::Collection collection = index.data( Akonadi::EntityTreeModel::CollectionRole ).value(); - if ( !collection.isValid() ) - return; + const Akonadi::Collection collection = index.data( Akonadi::EntityTreeModel::CollectionRole ).value(); + if ( !collection.isValid() ) + return; - SimpleCompletionItem *item = new SimpleCompletionItem( this, index.data().toString(), QString::number( collection.id() ), 60 ); - item->setIcon( index.data( Qt::DecorationRole ).value() ); + SimpleCompletionItem *item = new SimpleCompletionItem( this, index.data().toString(), QString::number( collection.id() ), 60 ); + item->setIcon( index.data( Qt::DecorationRole ).value() ); - new CompletionViewItem( mListView, item, 0 ); + new CompletionViewItem( mListView, item, 0 ); } void CompletionOrderEditor::loadCompletionItems() { - // The first step is to gather all the data, creating CompletionItem objects - foreach ( KLDAP::LdapClient *client, mLdapSearch->clients() ) { - new CompletionViewItem( mListView, new LDAPCompletionItem( client ), 0 ); - } - - Akonadi::ChangeRecorder *monitor = new Akonadi::ChangeRecorder( this ); - monitor->fetchCollection( true ); - monitor->setCollectionMonitored( Akonadi::Collection::root() ); - monitor->setMimeTypeMonitored( KABC::Addressee::mimeType(), true ); - monitor->setMimeTypeMonitored( KABC::ContactGroup::mimeType(), true ); - - Akonadi::EntityTreeModel *model = new Akonadi::EntityTreeModel( monitor, this ); - model->setItemPopulationStrategy( Akonadi::EntityTreeModel::NoItemPopulation ); - - KDescendantsProxyModel *descendantsProxy = new KDescendantsProxyModel( this ); - descendantsProxy->setDisplayAncestorData( true ); - descendantsProxy->setSourceModel( model ); - - Akonadi::CollectionFilterProxyModel *mimeTypeProxy = new Akonadi::CollectionFilterProxyModel( this ); - mimeTypeProxy->addMimeTypeFilters( QStringList() << KABC::Addressee::mimeType() - << KABC::ContactGroup::mimeType() ); - mimeTypeProxy->setSourceModel( descendantsProxy ); - mimeTypeProxy->setExcludeVirtualCollections( true ); - - mCollectionModel = mimeTypeProxy; + // The first step is to gather all the data, creating CompletionItem objects + foreach ( KLDAP::LdapClient *client, mLdapSearch->clients() ) { + new CompletionViewItem( mListView, new LDAPCompletionItem( client ), 0 ); + } + + Akonadi::ChangeRecorder *monitor = new Akonadi::ChangeRecorder( this ); + monitor->fetchCollection( true ); + monitor->setCollectionMonitored( Akonadi::Collection::root() ); + monitor->setMimeTypeMonitored( KABC::Addressee::mimeType(), true ); + monitor->setMimeTypeMonitored( KABC::ContactGroup::mimeType(), true ); + + Akonadi::EntityTreeModel *model = new Akonadi::EntityTreeModel( monitor, this ); + model->setItemPopulationStrategy( Akonadi::EntityTreeModel::NoItemPopulation ); + + KDescendantsProxyModel *descendantsProxy = new KDescendantsProxyModel( this ); + descendantsProxy->setDisplayAncestorData( true ); + descendantsProxy->setSourceModel( model ); - connect( mimeTypeProxy, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(rowsInserted(QModelIndex,int,int)) ); + Akonadi::CollectionFilterProxyModel *mimeTypeProxy = new Akonadi::CollectionFilterProxyModel( this ); + mimeTypeProxy->addMimeTypeFilters( QStringList() << KABC::Addressee::mimeType() + << KABC::ContactGroup::mimeType() ); + mimeTypeProxy->setSourceModel( descendantsProxy ); + mimeTypeProxy->setExcludeVirtualCollections( true ); - for ( int row = 0; row < mCollectionModel->rowCount(); ++row ) - addCompletionItemForIndex( mCollectionModel->index( row, 0 ) ); + mCollectionModel = mimeTypeProxy; - mListView->sortItems( 0, Qt::AscendingOrder ); + connect( mimeTypeProxy, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(rowsInserted(QModelIndex,int,int)) ); + + for ( int row = 0; row < mCollectionModel->rowCount(); ++row ) + addCompletionItemForIndex( mCollectionModel->index( row, 0 ) ); + + mListView->sortItems( 0, Qt::AscendingOrder ); } void CompletionOrderEditor::rowsInserted( const QModelIndex &parent, int start, int end ) { - for ( int row = start; row <= end; ++row ) - addCompletionItemForIndex( mCollectionModel->index( row, 0, parent ) ); + for ( int row = start; row <= end; ++row ) + addCompletionItemForIndex( mCollectionModel->index( row, 0, parent ) ); - mListView->sortItems( 0, Qt::AscendingOrder ); + mListView->sortItems( 0, Qt::AscendingOrder ); } void CompletionOrderEditor::slotSelectionChanged() { - QTreeWidgetItem *item = mListView->currentItem(); - mDownButton->setEnabled( item && mListView->itemBelow( item ) ); - mUpButton->setEnabled( item && mListView->itemAbove( item ) ); + QTreeWidgetItem *item = mListView->currentItem(); + mDownButton->setEnabled( item && mListView->itemBelow( item ) ); + mUpButton->setEnabled( item && mListView->itemAbove( item ) ); } static void swapItems( CompletionViewItem *one, CompletionViewItem *other ) { - CompletionItem* oneCompletion = one->item(); - CompletionItem* otherCompletion = other->item(); + CompletionItem* oneCompletion = one->item(); + CompletionItem* otherCompletion = other->item(); - int weight = otherCompletion->completionWeight(); - otherCompletion->setCompletionWeight( oneCompletion->completionWeight() ); - oneCompletion->setCompletionWeight( weight ); + int weight = otherCompletion->completionWeight(); + otherCompletion->setCompletionWeight( oneCompletion->completionWeight() ); + oneCompletion->setCompletionWeight( weight ); - one->setItem( otherCompletion ); - other->setItem( oneCompletion ); + one->setItem( otherCompletion ); + other->setItem( oneCompletion ); } void CompletionOrderEditor::slotMoveUp() { - CompletionViewItem *item = static_cast( mListView->currentItem() ); - if ( !item ) return; - CompletionViewItem *above = static_cast( mListView->itemAbove( item ) ); - if ( !above ) return; - swapItems( item, above ); - mListView->setCurrentItem( above, 0, QItemSelectionModel::Select | QItemSelectionModel::Current ); - mListView->sortItems( 0, Qt::AscendingOrder ); - mDirty = true; + CompletionViewItem *item = static_cast( mListView->currentItem() ); + if ( !item ) return; + CompletionViewItem *above = static_cast( mListView->itemAbove( item ) ); + if ( !above ) return; + swapItems( item, above ); + mListView->setCurrentItem( above, 0, QItemSelectionModel::Select | QItemSelectionModel::Current ); + mListView->sortItems( 0, Qt::AscendingOrder ); + mDirty = true; } void CompletionOrderEditor::slotMoveDown() { - CompletionViewItem *item = static_cast( mListView->currentItem() ); - if ( !item ) return; - CompletionViewItem *below = static_cast( mListView->itemBelow( item ) ); - if ( !below ) return; - swapItems( item, below ); - mListView->setCurrentItem( below ); - mListView->setCurrentItem( below, 0, QItemSelectionModel::Select | QItemSelectionModel::Current ); - mListView->sortItems( 0, Qt::AscendingOrder ); - mDirty = true; + CompletionViewItem *item = static_cast( mListView->currentItem() ); + if ( !item ) return; + CompletionViewItem *below = static_cast( mListView->itemBelow( item ) ); + if ( !below ) return; + swapItems( item, below ); + mListView->setCurrentItem( below ); + mListView->setCurrentItem( below, 0, QItemSelectionModel::Select | QItemSelectionModel::Current ); + mListView->sortItems( 0, Qt::AscendingOrder ); + mDirty = true; } void CompletionOrderEditor::slotOk() { - if ( mDirty ) { - int w = 100; - for ( int itemIndex = 0; itemIndex < mListView->topLevelItemCount(); ++itemIndex ) { - CompletionViewItem *item = - static_cast( mListView->topLevelItem( itemIndex ) ); - item->item()->setCompletionWeight( w ); - item->item()->save( this ); - --w; - } - emit completionOrderChanged(); - } - KDialog::accept(); + if ( mDirty ) { + int w = 100; + for ( int itemIndex = 0; itemIndex < mListView->topLevelItemCount(); ++itemIndex ) { + CompletionViewItem *item = + static_cast( mListView->topLevelItem( itemIndex ) ); + item->item()->setCompletionWeight( w ); + item->item()->save( this ); + --w; + } + emit completionOrderChanged(); + } + KDialog::accept(); } #include "moc_completionordereditor_p.cpp" diff -Nru kdepim-4.12.97/libkdepim/addressline/completionordereditor.h kdepim-4.13.0/libkdepim/addressline/completionordereditor.h --- kdepim-4.12.97/libkdepim/addressline/completionordereditor.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/addressline/completionordereditor.h 2014-04-10 07:40:20.000000000 +0000 @@ -52,7 +52,7 @@ // Base class for items in the list class CompletionItem { - public: +public: virtual ~CompletionItem() {} virtual QString label() const = 0; virtual QIcon icon() const = 0; @@ -64,25 +64,25 @@ class KDEPIM_EXPORT CompletionOrderEditor : public KDialog { - Q_OBJECT + Q_OBJECT - public: +public: CompletionOrderEditor( KLDAP::LdapClientSearch* ldapSearch, QWidget* parent ); ~CompletionOrderEditor(); KConfig* configFile() { return &mConfig; } - Q_SIGNALS: +Q_SIGNALS: void completionOrderChanged(); - private Q_SLOTS: +private Q_SLOTS: void rowsInserted( const QModelIndex &parent, int start, int end ); void slotSelectionChanged(); void slotMoveUp(); void slotMoveDown(); void slotOk(); - private: +private: void readConfig(); void writeConfig(); void loadCompletionItems(); diff -Nru kdepim-4.12.97/libkdepim/addressline/kmailcompletion.cpp kdepim-4.13.0/libkdepim/addressline/kmailcompletion.cpp --- kdepim-4.12.97/libkdepim/addressline/kmailcompletion.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/addressline/kmailcompletion.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -27,86 +27,86 @@ KMailCompletion::KMailCompletion() { - setIgnoreCase( true ); + setIgnoreCase( true ); } void KMailCompletion::clear() { - m_keyMap.clear(); - KCompletion::clear(); + m_keyMap.clear(); + KCompletion::clear(); } QString KMailCompletion::makeCompletion( const QString &string ) { - QString match = KCompletion::makeCompletion( string ); + QString match = KCompletion::makeCompletion( string ); - // this should be in postProcessMatch, but postProcessMatch is const and will not allow nextMatch - if ( !match.isEmpty() ){ - const QString firstMatch( match ); - while ( match.indexOf( QRegExp( QLatin1String("(@)|(<.*>)") ) ) == -1 ) { - /* local email do not require @domain part, if match is an address we'll + // this should be in postProcessMatch, but postProcessMatch is const and will not allow nextMatch + if ( !match.isEmpty() ){ + const QString firstMatch( match ); + while ( match.indexOf( QRegExp( QLatin1String("(@)|(<.*>)") ) ) == -1 ) { + /* local email do not require @domain part, if match is an address we'll * find last+first in m_keyMap and we'll know that match is * already a valid email. * * Distribution list do not have last+first entry, they will be * in mailAddr */ - const QStringList &mailAddr = m_keyMap[ match ]; //get all mailAddr for this keyword - bool isEmail = false; - for ( QStringList::ConstIterator sit( mailAddr.begin() ), sEnd( mailAddr.end() ); - sit != sEnd; ++sit ) { - if ( (*sit).indexOf( QLatin1Char('<') + match + QLatin1Char('>') ) != -1 || (*sit) == match ) { - isEmail = true; - break; + const QStringList &mailAddr = m_keyMap[ match ]; //get all mailAddr for this keyword + bool isEmail = false; + for ( QStringList::ConstIterator sit( mailAddr.begin() ), sEnd( mailAddr.end() ); + sit != sEnd; ++sit ) { + if ( (*sit).indexOf( QLatin1Char('<') + match + QLatin1Char('>') ) != -1 || (*sit) == match ) { + isEmail = true; + break; + } + } + + if ( !isEmail ) { + // match is a keyword, skip it and try to find match + match = nextMatch(); + if ( firstMatch == match ){ + match.clear(); + break; + } + } else { + break; + } } - } - - if ( !isEmail ) { - // match is a keyword, skip it and try to find match - match = nextMatch(); - if ( firstMatch == match ){ - match.clear(); - break; - } - } else { - break; - } } - } - return match; + return match; } void KMailCompletion::addItemWithKeys( const QString &email, int weight, const QStringList *keyWords ) { - Q_ASSERT( keyWords != 0 ); - QStringList::ConstIterator end = keyWords->constEnd(); - for ( QStringList::ConstIterator it( keyWords->constBegin() ); it != end; ++it ) { - QStringList &emailList = m_keyMap[ (*it) ]; //lookup email-list for given keyword - if ( emailList.indexOf( email ) == -1 ) { //add email if not there - emailList.append( email ); - } - addItem( (*it), weight ); //inform KCompletion about keyword + Q_ASSERT( keyWords != 0 ); + QStringList::ConstIterator end = keyWords->constEnd(); + for ( QStringList::ConstIterator it( keyWords->constBegin() ); it != end; ++it ) { + QStringList &emailList = m_keyMap[ (*it) ]; //lookup email-list for given keyword + if ( emailList.indexOf( email ) == -1 ) { //add email if not there + emailList.append( email ); + } + addItem( (*it), weight ); //inform KCompletion about keyword } } void KMailCompletion::postProcessMatches( QStringList *pMatches ) const { - Q_ASSERT( pMatches != 0 ); - if ( pMatches->isEmpty() ) { - return; - } - - //KCompletion has found the keywords for us, we can now map them to mail-addr - QSet< QString > mailAddrDistinct; - for ( QStringList::ConstIterator sit( pMatches->begin() ), sEnd( pMatches->end() ); - sit != sEnd; ++sit ) { - const QStringList &mailAddr = m_keyMap[ (*sit) ]; //get all mailAddr for this keyword - for ( QStringList::ConstIterator sit( mailAddr.begin() ), sEnd( mailAddr.end() ); + Q_ASSERT( pMatches != 0 ); + if ( pMatches->isEmpty() ) { + return; + } + + //KCompletion has found the keywords for us, we can now map them to mail-addr + QSet< QString > mailAddrDistinct; + for ( QStringList::ConstIterator sit( pMatches->begin() ), sEnd( pMatches->end() ); sit != sEnd; ++sit ) { - mailAddrDistinct.insert( *sit ); //store mailAddr, QSet will make them unique + const QStringList &mailAddr = m_keyMap[ (*sit) ]; //get all mailAddr for this keyword + for ( QStringList::ConstIterator sit( mailAddr.begin() ), sEnd( mailAddr.end() ); + sit != sEnd; ++sit ) { + mailAddrDistinct.insert( *sit ); //store mailAddr, QSet will make them unique + } } - } - pMatches->clear(); //delete keywords - (*pMatches) += mailAddrDistinct.toList(); //add emailAddr + pMatches->clear(); //delete keywords + (*pMatches) += mailAddrDistinct.toList(); //add emailAddr } diff -Nru kdepim-4.12.97/libkdepim/addressline/kmailcompletion.h kdepim-4.13.0/libkdepim/addressline/kmailcompletion.h --- kdepim-4.12.97/libkdepim/addressline/kmailcompletion.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/addressline/kmailcompletion.h 2014-04-10 07:40:20.000000000 +0000 @@ -38,9 +38,9 @@ */ class KMailCompletion : public KCompletion { - Q_OBJECT + Q_OBJECT - public: +public: KMailCompletion(); /** @@ -77,7 +77,7 @@ // to override the other postProcessMatches() function using KCompletion::postProcessMatches; - private: +private: QMap< QString, QStringList > m_keyMap; }; diff -Nru kdepim-4.12.97/libkdepim/addressline/recentaddresses.cpp kdepim-4.13.0/libkdepim/addressline/recentaddresses.cpp --- kdepim-4.12.97/libkdepim/addressline/recentaddresses.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/addressline/recentaddresses.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -254,13 +254,10 @@ void RecentAddressDialog::slotAddItem() { - QStringList lst = addresses(); mListView->blockSignals(true); - QStringList newList; - newList << QString() << lst; - setAddresses(newList); + mListView->insertItem(0, QString()); mListView->blockSignals(false); - mListView->setCurrentRow(0); + mListView->setCurrentRow(0, QItemSelectionModel::ClearAndSelect); mLineEdit->setFocus(); updateButtonState(); } diff -Nru kdepim-4.12.97/libkdepim/job/addcontactjob.cpp kdepim-4.13.0/libkdepim/job/addcontactjob.cpp --- kdepim-4.12.97/libkdepim/job/addcontactjob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/job/addcontactjob.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -34,99 +34,99 @@ class AddContactJob::Private { - public: +public: Private( AddContactJob *qq, const KABC::Addressee &contact, QWidget *parentWidget ) - : q( qq ), mContact( contact ), mParentWidget( parentWidget ), mShowMessageBox(true) + : q( qq ), mContact( contact ), mParentWidget( parentWidget ), mShowMessageBox(true) { } Private( AddContactJob *qq, const KABC::Addressee &contact, const Akonadi::Collection &collection ) - : q( qq ), mContact( contact ), mParentWidget( 0 ), mCollection( collection ), mShowMessageBox(true) + : q( qq ), mContact( contact ), mParentWidget( 0 ), mCollection( collection ), mShowMessageBox(true) { } void slotSearchDone( KJob *job ) { - if ( job->error() ) { - q->setError( job->error() ); - q->setErrorText( job->errorText() ); - q->emitResult(); - return; - } + if ( job->error() ) { + q->setError( job->error() ); + q->setErrorText( job->errorText() ); + q->emitResult(); + return; + } - const Akonadi::ContactSearchJob *searchJob = qobject_cast( job ); + const Akonadi::ContactSearchJob *searchJob = qobject_cast( job ); - const KABC::Addressee::List contacts = searchJob->contacts(); + const KABC::Addressee::List contacts = searchJob->contacts(); - if ( !contacts.isEmpty() ) { // contact is already part of the address book... - if(mShowMessageBox) { - const QString text = - i18nc( "@info", - "The vCard's primary email address is already in " - "your address book; however, you may save the vCard into " - "a file and import it into the address book manually." ); - KMessageBox::information( mParentWidget, text ); + if ( !contacts.isEmpty() ) { // contact is already part of the address book... + if(mShowMessageBox) { + const QString text = + i18nc( "@info", + "The vCard's primary email address is already in " + "your address book; however, you may save the vCard into " + "a file and import it into the address book manually." ); + KMessageBox::information( mParentWidget, text ); + } + q->setError( UserDefinedError ); + q->emitResult(); + return; + } + + if ( !mCollection.isValid() ) { + // ask user in which address book the new contact shall be stored + QPointer dlg = new SelectedCollectionDialog( mParentWidget ); + + bool gotIt = true; + if ( !dlg->exec() ) { + q->setError( UserDefinedError ); + q->emitResult(); + gotIt = false; + } else { + mCollection = dlg->selectedCollection(); + } + delete dlg; + if ( !gotIt ) { + return; + } } - q->setError( UserDefinedError ); - q->emitResult(); - return; - } - if ( !mCollection.isValid() ) { - // ask user in which address book the new contact shall be stored - QPointer dlg = new SelectedCollectionDialog( mParentWidget ); - - bool gotIt = true; - if ( !dlg->exec() ) { - q->setError( UserDefinedError ); - q->emitResult(); - gotIt = false; + if ( mCollection.isValid() ) { + // create the new item + Akonadi::Item item; + item.setMimeType( KABC::Addressee::mimeType() ); + item.setPayload( mContact ); + + // save the new item in akonadi storage + Akonadi::ItemCreateJob *job = new Akonadi::ItemCreateJob( item, mCollection ); + q->connect( job, SIGNAL(result(KJob*)), SLOT(slotAddContactDone(KJob*)) ); } else { - mCollection = dlg->selectedCollection(); + q->setError( UserDefinedError ); + q->emitResult(); } - delete dlg; - if ( !gotIt ) { - return; - } - } - - if ( mCollection.isValid() ) { - // create the new item - Akonadi::Item item; - item.setMimeType( KABC::Addressee::mimeType() ); - item.setPayload( mContact ); - - // save the new item in akonadi storage - Akonadi::ItemCreateJob *job = new Akonadi::ItemCreateJob( item, mCollection ); - q->connect( job, SIGNAL(result(KJob*)), SLOT(slotAddContactDone(KJob*)) ); - } else { - q->setError( UserDefinedError ); - q->emitResult(); - } } void slotAddContactDone( KJob *job ) { - if ( job->error() ) { - q->setError( job->error() ); - q->setErrorText( job->errorText() ); - q->emitResult(); - return; - } + if ( job->error() ) { + q->setError( job->error() ); + q->setErrorText( job->errorText() ); + q->emitResult(); + return; + } - if(mShowMessageBox) { - const QString text = - i18nc( "@info", - "The vCard was added to your address book; " - "you can add more information to this " - "entry by opening the address book." ); - KMessageBox::information( - mParentWidget, - text, - QString(), - QLatin1String("addedtokabc") ); - } - q->emitResult(); + if(mShowMessageBox) { + const QString text = + i18nc( "@info", + "The vCard was added to your address book; " + "you can add more information to this " + "entry by opening the address book." ); + KMessageBox::information( + mParentWidget, + text, + QString(), + QLatin1String("addedtokabc") ); + } + q->emitResult(); } AddContactJob *q; @@ -137,18 +137,18 @@ }; AddContactJob::AddContactJob( const KABC::Addressee &contact, QWidget *parentWidget, QObject *parent ) - : KJob( parent ), d( new Private( this, contact, parentWidget ) ) + : KJob( parent ), d( new Private( this, contact, parentWidget ) ) { } AddContactJob::AddContactJob( const KABC::Addressee &contact, const Akonadi::Collection &collection, QObject *parent ) - : KJob( parent ), d( new Private( this, contact, collection ) ) + : KJob( parent ), d( new Private( this, contact, collection ) ) { } AddContactJob::~AddContactJob() { - delete d; + delete d; } void AddContactJob::showMessageBox(bool b) @@ -158,13 +158,13 @@ void AddContactJob::start() { - // first check whether a contact with the same email exists already - Akonadi::ContactSearchJob *searchJob = new Akonadi::ContactSearchJob( this ); - searchJob->setLimit( 1 ); - searchJob->setQuery( Akonadi::ContactSearchJob::Email, d->mContact.preferredEmail().toLower(), - Akonadi::ContactSearchJob::ExactMatch ); + // first check whether a contact with the same email exists already + Akonadi::ContactSearchJob *searchJob = new Akonadi::ContactSearchJob( this ); + searchJob->setLimit( 1 ); + searchJob->setQuery( Akonadi::ContactSearchJob::Email, d->mContact.preferredEmail().toLower(), + Akonadi::ContactSearchJob::ExactMatch ); - connect( searchJob, SIGNAL(result(KJob*)), SLOT(slotSearchDone(KJob*)) ); + connect( searchJob, SIGNAL(result(KJob*)), SLOT(slotSearchDone(KJob*)) ); } #include "moc_addcontactjob.cpp" diff -Nru kdepim-4.12.97/libkdepim/job/addcontactjob.h kdepim-4.13.0/libkdepim/job/addcontactjob.h --- kdepim-4.12.97/libkdepim/job/addcontactjob.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/job/addcontactjob.h 2014-04-10 07:40:20.000000000 +0000 @@ -42,9 +42,9 @@ */ class KDEPIM_EXPORT AddContactJob : public KJob { - Q_OBJECT + Q_OBJECT - public: +public: /** * Creates a new add contact job. * @@ -78,7 +78,7 @@ void showMessageBox(bool b); - private: +private: //@cond PRIVATE class Private; Private* const d; diff -Nru kdepim-4.12.97/libkdepim/job/addemailaddressjob.cpp kdepim-4.13.0/libkdepim/job/addemailaddressjob.cpp --- kdepim-4.12.97/libkdepim/job/addemailaddressjob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/job/addemailaddressjob.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -49,20 +49,20 @@ class AddEmailAddressJob::Private { - public: +public: Private( AddEmailAddressJob *qq, const QString &emailString, QWidget *parentWidget ) - : q( qq ), mCompleteAddress( emailString ), mParentWidget( parentWidget ) + : q( qq ), mCompleteAddress( emailString ), mParentWidget( parentWidget ) { - KABC::Addressee::parseEmailAddress( emailString, mName, mEmail ); + KABC::Addressee::parseEmailAddress( emailString, mName, mEmail ); } void slotResourceCreationDone( KJob* job ) { if ( job->error() ) { - q->setError( job->error() ); - q->setErrorText( job->errorText() ); - q->emitResult(); - return; + q->setError( job->error() ); + q->setErrorText( job->errorText() ); + q->emitResult(); + return; } createContact(); } @@ -70,182 +70,182 @@ void slotSearchDone( KJob *job ) { - if ( job->error() ) { - q->setError( job->error() ); - q->setErrorText( job->errorText() ); - q->emitResult(); - return; - } + if ( job->error() ) { + q->setError( job->error() ); + q->setErrorText( job->errorText() ); + q->emitResult(); + return; + } - const Akonadi::ContactSearchJob *searchJob = qobject_cast( job ); + const Akonadi::ContactSearchJob *searchJob = qobject_cast( job ); - const KABC::Addressee::List contacts = searchJob->contacts(); - if ( !contacts.isEmpty() ) { - const QString text = - i18nc( "@info", - "A contact with the email address %1 " - "is already in your address book.", Qt::escape(mCompleteAddress) ); - - KMessageBox::information( - mParentWidget, - text, - QString(), - QLatin1String( "alreadyInAddressBook" ) ); - q->setError( UserDefinedError ); - q->emitResult(); - return; - } - createContact(); + const KABC::Addressee::List contacts = searchJob->contacts(); + if ( !contacts.isEmpty() ) { + const QString text = + i18nc( "@info", + "A contact with the email address %1 " + "is already in your address book.", Qt::escape(mCompleteAddress) ); + + KMessageBox::information( + mParentWidget, + text, + QString(), + QLatin1String( "alreadyInAddressBook" ) ); + q->setError( UserDefinedError ); + q->emitResult(); + return; + } + createContact(); } void createContact() { - const QStringList mimeTypes( KABC::Addressee::mimeType() ); + const QStringList mimeTypes( KABC::Addressee::mimeType() ); - Akonadi::CollectionFetchJob * const addressBookJob = - new Akonadi::CollectionFetchJob( Akonadi::Collection::root(), - Akonadi::CollectionFetchJob::Recursive ); + Akonadi::CollectionFetchJob * const addressBookJob = + new Akonadi::CollectionFetchJob( Akonadi::Collection::root(), + Akonadi::CollectionFetchJob::Recursive ); - addressBookJob->fetchScope().setContentMimeTypes( mimeTypes ); - q->connect( addressBookJob, SIGNAL(result(KJob*)), SLOT(slotCollectionsFetched(KJob*)) ); + addressBookJob->fetchScope().setContentMimeTypes( mimeTypes ); + q->connect( addressBookJob, SIGNAL(result(KJob*)), SLOT(slotCollectionsFetched(KJob*)) ); } void slotCollectionsFetched( KJob *job ) { - if ( job->error() ) { - q->setError( job->error() ); - q->setErrorText( job->errorText() ); - q->emitResult(); - return; - } + if ( job->error() ) { + q->setError( job->error() ); + q->setErrorText( job->errorText() ); + q->emitResult(); + return; + } - const Akonadi::CollectionFetchJob *addressBookJob = - qobject_cast( job ); + const Akonadi::CollectionFetchJob *addressBookJob = + qobject_cast( job ); - Akonadi::Collection::List canCreateItemCollections ; + Akonadi::Collection::List canCreateItemCollections ; - foreach ( const Akonadi::Collection &collection, addressBookJob->collections() ) { - if ( Akonadi::Collection::CanCreateItem & collection.rights() ) { - canCreateItemCollections.append(collection); - } - } - - Akonadi::Collection addressBook; - - const int nbItemCollection( canCreateItemCollections.size() ); - if ( nbItemCollection == 0 ) { - if(KMessageBox::questionYesNo( - mParentWidget, - i18nc( "@info", - "You must create an address book before adding a contact. Do you want to create an address book?" ), - i18nc( "@title:window", "No Address Book Available" ) ) == KMessageBox::Yes) { - Akonadi::AgentTypeDialog dlg( mParentWidget ); - dlg.setCaption( i18n("Add Address Book") ); - dlg.agentFilterProxyModel()->addMimeTypeFilter(KABC::Addressee::mimeType()); - dlg.agentFilterProxyModel()->addMimeTypeFilter(KABC::ContactGroup::mimeType()); - dlg.agentFilterProxyModel()->addCapabilityFilter( QLatin1String( "Resource" ) ); - - if ( dlg.exec() ) { - const Akonadi::AgentType agentType = dlg.agentType(); - - if ( agentType.isValid() ) { - Akonadi::AgentInstanceCreateJob *job = new Akonadi::AgentInstanceCreateJob( agentType, q ); - q->connect( job, SIGNAL(result(KJob*)), SLOT(slotResourceCreationDone(KJob*)) ); - job->configure( mParentWidget ); - job->start(); - return; - } else { //if agent is not valid => return error and finish job + foreach ( const Akonadi::Collection &collection, addressBookJob->collections() ) { + if ( Akonadi::Collection::CanCreateItem & collection.rights() ) { + canCreateItemCollections.append(collection); + } + } + + Akonadi::Collection addressBook; + + const int nbItemCollection( canCreateItemCollections.size() ); + if ( nbItemCollection == 0 ) { + if(KMessageBox::questionYesNo( + mParentWidget, + i18nc( "@info", + "You must create an address book before adding a contact. Do you want to create an address book?" ), + i18nc( "@title:window", "No Address Book Available" ) ) == KMessageBox::Yes) { + Akonadi::AgentTypeDialog dlg( mParentWidget ); + dlg.setCaption( i18n("Add Address Book") ); + dlg.agentFilterProxyModel()->addMimeTypeFilter(KABC::Addressee::mimeType()); + dlg.agentFilterProxyModel()->addMimeTypeFilter(KABC::ContactGroup::mimeType()); + dlg.agentFilterProxyModel()->addCapabilityFilter( QLatin1String( "Resource" ) ); + + if ( dlg.exec() ) { + const Akonadi::AgentType agentType = dlg.agentType(); + + if ( agentType.isValid() ) { + Akonadi::AgentInstanceCreateJob *job = new Akonadi::AgentInstanceCreateJob( agentType, q ); + q->connect( job, SIGNAL(result(KJob*)), SLOT(slotResourceCreationDone(KJob*)) ); + job->configure( mParentWidget ); + job->start(); + return; + } else { //if agent is not valid => return error and finish job + q->setError( UserDefinedError ); + q->emitResult(); + return; + } + } else { //Canceled create agent => return error and finish job + q->setError( UserDefinedError ); + q->emitResult(); + return; + } + } else { q->setError( UserDefinedError ); q->emitResult(); return; - } - } else { //Canceled create agent => return error and finish job - q->setError( UserDefinedError ); - q->emitResult(); - return; } + } else if ( nbItemCollection == 1 ) { + addressBook = canCreateItemCollections[0]; } else { - q->setError( UserDefinedError ); - q->emitResult(); - return; - } - } else if ( nbItemCollection == 1 ) { - addressBook = canCreateItemCollections[0]; - } else { - // ask user in which address book the new contact shall be stored - QPointer dlg = new SelectedCollectionDialog( mParentWidget ); - - bool gotIt = true; - if ( dlg->exec() ) { - addressBook = dlg->selectedCollection(); - } else { - q->setError( UserDefinedError ); - q->emitResult(); - gotIt = false; - } - delete dlg; - if ( !gotIt ) { - return; + // ask user in which address book the new contact shall be stored + QPointer dlg = new SelectedCollectionDialog( mParentWidget ); + + bool gotIt = true; + if ( dlg->exec() ) { + addressBook = dlg->selectedCollection(); + } else { + q->setError( UserDefinedError ); + q->emitResult(); + gotIt = false; + } + delete dlg; + if ( !gotIt ) { + return; + } } - } - if ( !addressBook.isValid() ) { - q->setError( UserDefinedError ); - q->emitResult(); - return; - } - KABC::Addressee contact; - contact.setNameFromString( mName ); - contact.insertEmail( mEmail, true ); - - // create the new item - Akonadi::Item item; - item.setMimeType( KABC::Addressee::mimeType() ); - item.setPayload( contact ); - - // save the new item in akonadi storage - Akonadi::ItemCreateJob *createJob = new Akonadi::ItemCreateJob( item, addressBook, q ); - q->connect( createJob, SIGNAL(result(KJob*)), SLOT(slotAddContactDone(KJob*)) ); + if ( !addressBook.isValid() ) { + q->setError( UserDefinedError ); + q->emitResult(); + return; + } + KABC::Addressee contact; + contact.setNameFromString( mName ); + contact.insertEmail( mEmail, true ); + + // create the new item + Akonadi::Item item; + item.setMimeType( KABC::Addressee::mimeType() ); + item.setPayload( contact ); + + // save the new item in akonadi storage + Akonadi::ItemCreateJob *createJob = new Akonadi::ItemCreateJob( item, addressBook, q ); + q->connect( createJob, SIGNAL(result(KJob*)), SLOT(slotAddContactDone(KJob*)) ); } void slotAddContactDone( KJob *job ) { - if ( job->error() ) { - q->setError( job->error() ); - q->setErrorText( job->errorText() ); - q->emitResult(); - return; - } + if ( job->error() ) { + q->setError( job->error() ); + q->setErrorText( job->errorText() ); + q->emitResult(); + return; + } - const Akonadi::ItemCreateJob *createJob = qobject_cast( job ); - mItem = createJob->item(); + const Akonadi::ItemCreateJob *createJob = qobject_cast( job ); + mItem = createJob->item(); - const QString text = - i18nc( "@info", - "A contact for %1 was successfully added " - "to your address book." - "Do you want to edit this new contact now?", - Qt::escape(mCompleteAddress) ); - - if ( KMessageBox::questionYesNo( - mParentWidget, - text, - QString(), - KStandardGuiItem::yes(), - KStandardGuiItem::no(), - QLatin1String( "addedtokabc" ) ) == KMessageBox::Yes ) { - QPointer dlg = - new Akonadi::ContactEditorDialog( Akonadi::ContactEditorDialog::EditMode, - mParentWidget ); - dlg->setContact( mItem ); - connect( dlg, SIGNAL(contactStored(Akonadi::Item)), - q, SLOT(contactStored(Akonadi::Item)) ); - connect( dlg, SIGNAL(error(QString)), - q, SLOT(slotContactEditorError(QString)) ); - dlg->exec(); - delete dlg; - } - q->emitResult(); + const QString text = + i18nc( "@info", + "A contact for %1 was successfully added " + "to your address book." + "Do you want to edit this new contact now?", + Qt::escape(mCompleteAddress) ); + + if ( KMessageBox::questionYesNo( + mParentWidget, + text, + QString(), + KStandardGuiItem::yes(), + KStandardGuiItem::no(), + QLatin1String( "addedtokabc" ) ) == KMessageBox::Yes ) { + QPointer dlg = + new Akonadi::ContactEditorDialog( Akonadi::ContactEditorDialog::EditMode, + mParentWidget ); + dlg->setContact( mItem ); + connect( dlg, SIGNAL(contactStored(Akonadi::Item)), + q, SLOT(contactStored(Akonadi::Item)) ); + connect( dlg, SIGNAL(error(QString)), + q, SLOT(slotContactEditorError(QString)) ); + dlg->exec(); + delete dlg; + } + q->emitResult(); } void slotContactEditorError(const QString &error) @@ -269,28 +269,28 @@ AddEmailAddressJob::AddEmailAddressJob( const QString &email, QWidget *parentWidget, QObject *parent ) - : KJob( parent ), d( new Private( this, email, parentWidget ) ) + : KJob( parent ), d( new Private( this, email, parentWidget ) ) { } AddEmailAddressJob::~AddEmailAddressJob() { - delete d; + delete d; } void AddEmailAddressJob::start() { - // first check whether a contact with the same email exists already - Akonadi::ContactSearchJob *searchJob = new Akonadi::ContactSearchJob( this ); - searchJob->setLimit( 1 ); - searchJob->setQuery( Akonadi::ContactSearchJob::Email, d->mEmail.toLower(), - Akonadi::ContactSearchJob::ExactMatch ); - connect( searchJob, SIGNAL(result(KJob*)), SLOT(slotSearchDone(KJob*)) ); + // first check whether a contact with the same email exists already + Akonadi::ContactSearchJob *searchJob = new Akonadi::ContactSearchJob( this ); + searchJob->setLimit( 1 ); + searchJob->setQuery( Akonadi::ContactSearchJob::Email, d->mEmail.toLower(), + Akonadi::ContactSearchJob::ExactMatch ); + connect( searchJob, SIGNAL(result(KJob*)), SLOT(slotSearchDone(KJob*)) ); } Akonadi::Item AddEmailAddressJob::contact() const { - return d->mItem; + return d->mItem; } #include "moc_addemailaddressjob.cpp" diff -Nru kdepim-4.12.97/libkdepim/job/addemailaddressjob.h kdepim-4.13.0/libkdepim/job/addemailaddressjob.h --- kdepim-4.12.97/libkdepim/job/addemailaddressjob.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/job/addemailaddressjob.h 2014-04-10 07:40:20.000000000 +0000 @@ -25,7 +25,7 @@ #include namespace Akonadi { - class Item; +class Item; } namespace KPIM { @@ -39,9 +39,9 @@ */ class KDEPIM_EXPORT AddEmailAddressJob : public KJob { - Q_OBJECT + Q_OBJECT - public: +public: /** * Creates a new add email address job. * @@ -66,7 +66,7 @@ */ Akonadi::Item contact() const; - private: +private: //@cond PRIVATE class Private; Private *const d; @@ -74,7 +74,7 @@ Q_PRIVATE_SLOT( d, void slotSearchDone( KJob* ) ) Q_PRIVATE_SLOT( d, void slotAddContactDone( KJob* ) ) Q_PRIVATE_SLOT( d, void slotCollectionsFetched( KJob* ) ) - Q_PRIVATE_SLOT( d, void slotResourceCreationDone( KJob* ) ) + Q_PRIVATE_SLOT( d, void slotResourceCreationDone( KJob* ) ) Q_PRIVATE_SLOT( d, void slotContactEditorError(const QString &) ) Q_PRIVATE_SLOT( d, void contactStored( const Akonadi::Item & ) ) diff -Nru kdepim-4.12.97/libkdepim/job/openemailaddressjob.cpp kdepim-4.13.0/libkdepim/job/openemailaddressjob.cpp --- kdepim-4.12.97/libkdepim/job/openemailaddressjob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/job/openemailaddressjob.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -34,57 +34,57 @@ class OpenEmailAddressJob::Private { - public: +public: Private( OpenEmailAddressJob *qq, const QString &emailString, QWidget *parentWidget ) - : q( qq ), mCompleteAddress( emailString ), mParentWidget( parentWidget ) + : q( qq ), mCompleteAddress( emailString ), mParentWidget( parentWidget ) { - KABC::Addressee::parseEmailAddress( emailString, mName, mEmail ); + KABC::Addressee::parseEmailAddress( emailString, mName, mEmail ); } void slotSearchDone( KJob *job ) { - if ( job->error() ) { - q->setError( job->error() ); - q->setErrorText( job->errorText() ); - q->emitResult(); - return; - } - - const Akonadi::ContactSearchJob *searchJob = qobject_cast( job ); - - const Akonadi::Item::List contacts = searchJob->items(); - if ( !contacts.isEmpty() ) { - // open the editor with the matching item - Akonadi::ContactEditorDialog dlg( Akonadi::ContactEditorDialog::EditMode, mParentWidget ); - dlg.setContact( contacts.first() ); - dlg.exec(); - - q->emitResult(); - return; - } - - AddEmailAddressJob *createJob = new AddEmailAddressJob( mCompleteAddress, mParentWidget, q ); - q->connect( createJob, SIGNAL(result(KJob*)), SLOT(slotAddContactDone(KJob*)) ); - createJob->start(); + if ( job->error() ) { + q->setError( job->error() ); + q->setErrorText( job->errorText() ); + q->emitResult(); + return; + } + + const Akonadi::ContactSearchJob *searchJob = qobject_cast( job ); + + const Akonadi::Item::List contacts = searchJob->items(); + if ( !contacts.isEmpty() ) { + // open the editor with the matching item + Akonadi::ContactEditorDialog dlg( Akonadi::ContactEditorDialog::EditMode, mParentWidget ); + dlg.setContact( contacts.first() ); + dlg.exec(); + + q->emitResult(); + return; + } + + AddEmailAddressJob *createJob = new AddEmailAddressJob( mCompleteAddress, mParentWidget, q ); + q->connect( createJob, SIGNAL(result(KJob*)), SLOT(slotAddContactDone(KJob*)) ); + createJob->start(); } void slotAddContactDone( KJob *job ) { - if ( job->error() ) { - q->setError( job->error() ); - q->setErrorText( job->errorText() ); - q->emitResult(); - return; - } + if ( job->error() ) { + q->setError( job->error() ); + q->setErrorText( job->errorText() ); + q->emitResult(); + return; + } - const AddEmailAddressJob *createJob = qobject_cast( job ); + const AddEmailAddressJob *createJob = qobject_cast( job ); - // open the editor with the matching item - Akonadi::ContactEditorDialog dlg( Akonadi::ContactEditorDialog::EditMode, mParentWidget ); - dlg.setContact( createJob->contact() ); - dlg.exec(); + // open the editor with the matching item + Akonadi::ContactEditorDialog dlg( Akonadi::ContactEditorDialog::EditMode, mParentWidget ); + dlg.setContact( createJob->contact() ); + dlg.exec(); - q->emitResult(); + q->emitResult(); } OpenEmailAddressJob *q; @@ -95,23 +95,23 @@ }; OpenEmailAddressJob::OpenEmailAddressJob( const QString &email, QWidget *parentWidget, QObject *parent ) - : KJob( parent ), d( new Private( this, email, parentWidget ) ) + : KJob( parent ), d( new Private( this, email, parentWidget ) ) { } OpenEmailAddressJob::~OpenEmailAddressJob() { - delete d; + delete d; } void OpenEmailAddressJob::start() { - // first check whether a contact with the same email exists already - Akonadi::ContactSearchJob *searchJob = new Akonadi::ContactSearchJob( this ); - searchJob->setLimit( 1 ); - searchJob->setQuery( Akonadi::ContactSearchJob::Email, d->mEmail.toLower(), - Akonadi::ContactSearchJob::ExactMatch ); - connect( searchJob, SIGNAL(result(KJob*)), SLOT(slotSearchDone(KJob*)) ); + // first check whether a contact with the same email exists already + Akonadi::ContactSearchJob *searchJob = new Akonadi::ContactSearchJob( this ); + searchJob->setLimit( 1 ); + searchJob->setQuery( Akonadi::ContactSearchJob::Email, d->mEmail.toLower(), + Akonadi::ContactSearchJob::ExactMatch ); + connect( searchJob, SIGNAL(result(KJob*)), SLOT(slotSearchDone(KJob*)) ); } #include "moc_openemailaddressjob.cpp" diff -Nru kdepim-4.12.97/libkdepim/job/openemailaddressjob.h kdepim-4.13.0/libkdepim/job/openemailaddressjob.h --- kdepim-4.12.97/libkdepim/job/openemailaddressjob.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/job/openemailaddressjob.h 2014-04-10 07:40:20.000000000 +0000 @@ -38,9 +38,9 @@ */ class KDEPIM_EXPORT OpenEmailAddressJob : public KJob { - Q_OBJECT + Q_OBJECT - public: +public: /** * Creates a new open email address job. * @@ -60,7 +60,7 @@ */ virtual void start(); - private: +private: //@cond PRIVATE class Private; Private* const d; diff -Nru kdepim-4.12.97/libkdepim/ldap/addhostdialog.cpp kdepim-4.13.0/libkdepim/ldap/addhostdialog.cpp --- kdepim-4.12.97/libkdepim/ldap/addhostdialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/ldap/addhostdialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -29,77 +29,77 @@ #include AddHostDialog::AddHostDialog( KLDAP::LdapServer *server, QWidget *parent ) - : KDialog( parent ) + : KDialog( parent ) { - setCaption( i18n( "Add Host" ) ); - setButtons( Ok | Cancel ); - setDefaultButton( Ok ); - setModal( true ); - showButtonSeparator( true ); - - mServer = server; - - QWidget *page = new QWidget( this ); - setMainWidget( page ); - QHBoxLayout *layout = new QHBoxLayout( page ); - layout->setSpacing( spacingHint() ); - layout->setMargin( 0 ); - - mCfg = new KLDAP::LdapConfigWidget( - KLDAP::LdapConfigWidget::W_USER | - KLDAP::LdapConfigWidget::W_PASS | - KLDAP::LdapConfigWidget::W_BINDDN | - KLDAP::LdapConfigWidget::W_REALM | - KLDAP::LdapConfigWidget::W_HOST | - KLDAP::LdapConfigWidget::W_PORT | - KLDAP::LdapConfigWidget::W_VER | - KLDAP::LdapConfigWidget::W_TIMELIMIT | - KLDAP::LdapConfigWidget::W_SIZELIMIT | - KLDAP::LdapConfigWidget::W_PAGESIZE | - KLDAP::LdapConfigWidget::W_DN | - KLDAP::LdapConfigWidget::W_SECBOX | - KLDAP::LdapConfigWidget::W_AUTHBOX, - page ); - - layout->addWidget( mCfg ); - mCfg->setHost( mServer->host() ); - mCfg->setPort( mServer->port() ); - mCfg->setDn( mServer->baseDn() ); - mCfg->setUser( mServer->user() ); - mCfg->setBindDn( mServer->bindDn() ); - mCfg->setPassword( mServer->password() ); - mCfg->setTimeLimit( mServer->timeLimit() ); - mCfg->setSizeLimit( mServer->sizeLimit() ); - mCfg->setPageSize( mServer->pageSize() ); - mCfg->setVersion( mServer->version() ); + setCaption( i18n( "Add Host" ) ); + setButtons( Ok | Cancel ); + setDefaultButton( Ok ); + setModal( true ); + showButtonSeparator( true ); + + mServer = server; + + QWidget *page = new QWidget( this ); + setMainWidget( page ); + QHBoxLayout *layout = new QHBoxLayout( page ); + layout->setSpacing( spacingHint() ); + layout->setMargin( 0 ); + + mCfg = new KLDAP::LdapConfigWidget( + KLDAP::LdapConfigWidget::W_USER | + KLDAP::LdapConfigWidget::W_PASS | + KLDAP::LdapConfigWidget::W_BINDDN | + KLDAP::LdapConfigWidget::W_REALM | + KLDAP::LdapConfigWidget::W_HOST | + KLDAP::LdapConfigWidget::W_PORT | + KLDAP::LdapConfigWidget::W_VER | + KLDAP::LdapConfigWidget::W_TIMELIMIT | + KLDAP::LdapConfigWidget::W_SIZELIMIT | + KLDAP::LdapConfigWidget::W_PAGESIZE | + KLDAP::LdapConfigWidget::W_DN | + KLDAP::LdapConfigWidget::W_SECBOX | + KLDAP::LdapConfigWidget::W_AUTHBOX, + page ); + + layout->addWidget( mCfg ); + mCfg->setHost( mServer->host() ); + mCfg->setPort( mServer->port() ); + mCfg->setDn( mServer->baseDn() ); + mCfg->setUser( mServer->user() ); + mCfg->setBindDn( mServer->bindDn() ); + mCfg->setPassword( mServer->password() ); + mCfg->setTimeLimit( mServer->timeLimit() ); + mCfg->setSizeLimit( mServer->sizeLimit() ); + mCfg->setPageSize( mServer->pageSize() ); + mCfg->setVersion( mServer->version() ); - switch ( mServer->security() ) { + switch ( mServer->security() ) { case KLDAP::LdapServer::TLS: - mCfg->setSecurity( KLDAP::LdapConfigWidget::TLS ); - break; + mCfg->setSecurity( KLDAP::LdapConfigWidget::TLS ); + break; case KLDAP::LdapServer::SSL: - mCfg->setSecurity( KLDAP::LdapConfigWidget::SSL ); - break; + mCfg->setSecurity( KLDAP::LdapConfigWidget::SSL ); + break; default: - mCfg->setSecurity( KLDAP::LdapConfigWidget::None ); - } + mCfg->setSecurity( KLDAP::LdapConfigWidget::None ); + } - switch ( mServer->auth() ) { + switch ( mServer->auth() ) { case KLDAP::LdapServer::Simple: - mCfg->setAuth( KLDAP::LdapConfigWidget::Simple ); - break; + mCfg->setAuth( KLDAP::LdapConfigWidget::Simple ); + break; case KLDAP::LdapServer::SASL: - mCfg->setAuth( KLDAP::LdapConfigWidget::SASL ); - break; + mCfg->setAuth( KLDAP::LdapConfigWidget::SASL ); + break; default: - mCfg->setAuth( KLDAP::LdapConfigWidget::Anonymous ); - } - mCfg->setMech( mServer->mech() ); - - KAcceleratorManager::manage( this ); - connect(mCfg, SIGNAL(hostNameChanged(QString)), this, SLOT(slotHostEditChanged(QString))); - connect( this, SIGNAL(okClicked()), SLOT(slotOk()) ); - enableButtonOk(!mServer->host().isEmpty()); + mCfg->setAuth( KLDAP::LdapConfigWidget::Anonymous ); + } + mCfg->setMech( mServer->mech() ); + + KAcceleratorManager::manage( this ); + connect(mCfg, SIGNAL(hostNameChanged(QString)), this, SLOT(slotHostEditChanged(QString))); + connect( this, SIGNAL(okClicked()), SLOT(slotOk()) ); + enableButtonOk(!mServer->host().isEmpty()); } AddHostDialog::~AddHostDialog() @@ -108,43 +108,43 @@ void AddHostDialog::slotHostEditChanged( const QString &text ) { - enableButtonOk( !text.isEmpty() ); + enableButtonOk( !text.isEmpty() ); } void AddHostDialog::slotOk() { - mServer->setHost( mCfg->host() ); - mServer->setPort( mCfg->port() ); - mServer->setBaseDn( mCfg->dn() ); - mServer->setUser( mCfg->user() ); - mServer->setBindDn( mCfg->bindDn() ); - mServer->setPassword( mCfg->password() ); - mServer->setTimeLimit( mCfg->timeLimit() ); - mServer->setSizeLimit( mCfg->sizeLimit() ); - mServer->setPageSize( mCfg->pageSize() ); - mServer->setVersion( mCfg->version() ); - switch ( mCfg->security() ) { + mServer->setHost( mCfg->host() ); + mServer->setPort( mCfg->port() ); + mServer->setBaseDn( mCfg->dn() ); + mServer->setUser( mCfg->user() ); + mServer->setBindDn( mCfg->bindDn() ); + mServer->setPassword( mCfg->password() ); + mServer->setTimeLimit( mCfg->timeLimit() ); + mServer->setSizeLimit( mCfg->sizeLimit() ); + mServer->setPageSize( mCfg->pageSize() ); + mServer->setVersion( mCfg->version() ); + switch ( mCfg->security() ) { case KLDAP::LdapConfigWidget::TLS: - mServer->setSecurity( KLDAP::LdapServer::TLS ); - break; + mServer->setSecurity( KLDAP::LdapServer::TLS ); + break; case KLDAP::LdapConfigWidget::SSL: - mServer->setSecurity( KLDAP::LdapServer::SSL ); - break; + mServer->setSecurity( KLDAP::LdapServer::SSL ); + break; default: - mServer->setSecurity( KLDAP::LdapServer::None ); - } - switch ( mCfg->auth() ) { + mServer->setSecurity( KLDAP::LdapServer::None ); + } + switch ( mCfg->auth() ) { case KLDAP::LdapConfigWidget::Simple: - mServer->setAuth( KLDAP::LdapServer::Simple ); - break; + mServer->setAuth( KLDAP::LdapServer::Simple ); + break; case KLDAP::LdapConfigWidget::SASL: - mServer->setAuth( KLDAP::LdapServer::SASL ); - break; + mServer->setAuth( KLDAP::LdapServer::SASL ); + break; default: - mServer->setAuth( KLDAP::LdapServer::Anonymous ); - } - mServer->setMech( mCfg->mech() ); - KDialog::accept(); + mServer->setAuth( KLDAP::LdapServer::Anonymous ); + } + mServer->setMech( mCfg->mech() ); + KDialog::accept(); } #include "moc_addhostdialog_p.cpp" diff -Nru kdepim-4.12.97/libkdepim/ldap/kcmldap.cpp kdepim-4.13.0/libkdepim/ldap/kcmldap.cpp --- kdepim-4.12.97/libkdepim/ldap/kcmldap.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/ldap/kcmldap.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -55,21 +55,21 @@ class LDAPItem : public QListWidgetItem { - public: +public: LDAPItem( QListWidget *parent, const KLDAP::LdapServer &server, bool isActive = false ) - : QListWidgetItem( parent, QListWidgetItem::UserType ), - mIsActive( isActive ) + : QListWidgetItem( parent, QListWidgetItem::UserType ), + mIsActive( isActive ) { - setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable ); - setCheckState( isActive ? Qt::Checked : Qt::Unchecked ); - setServer( server ); + setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable ); + setCheckState( isActive ? Qt::Checked : Qt::Unchecked ); + setServer( server ); } void setServer( const KLDAP::LdapServer &server ) { - mServer = server; + mServer = server; - setText( mServer.host() ); + setText( mServer.host() ); } const KLDAP::LdapServer &server() const { return mServer; } @@ -77,35 +77,35 @@ void setIsActive( bool isActive ) { mIsActive = isActive; } bool isActive() const { return mIsActive; } - private: +private: KLDAP::LdapServer mServer; bool mIsActive; }; KCMLdap::KCMLdap( QWidget *parent, const QVariantList& ) - : KCModule( KCMLdapFactory::componentData(), parent ) + : KCModule( KCMLdapFactory::componentData(), parent ) { - setButtons(KCModule::Apply); - KAboutData *about = new KAboutData( I18N_NOOP( "kcmldap" ), 0, - ki18n( "LDAP Server Settings" ), - 0, KLocalizedString(), KAboutData::License_LGPL, - ki18n( "(c) 2009 - 2010 Tobias Koenig" ) ); - - about->addAuthor( ki18n( "Tobias Koenig" ), KLocalizedString(), "tokoe@kde.org" ); - KGlobal::locale()->insertCatalog(QLatin1String("libkdepim")); - setAboutData( about ); - mClientSearchConfig = new KLDAP::LdapClientSearchConfig; - initGUI(); - - connect( mHostListView, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), - this, SLOT(slotSelectionChanged(QListWidgetItem*)) ); - connect( mHostListView, SIGNAL(itemDoubleClicked(QListWidgetItem*)), - this, SLOT(slotEditHost()) ); - connect( mHostListView, SIGNAL(itemClicked(QListWidgetItem*)), - this, SLOT(slotItemClicked(QListWidgetItem*)) ); + setButtons(KCModule::Apply); + KAboutData *about = new KAboutData( I18N_NOOP( "kcmldap" ), 0, + ki18n( "LDAP Server Settings" ), + 0, KLocalizedString(), KAboutData::License_LGPL, + ki18n( "(c) 2009 - 2010 Tobias Koenig" ) ); + + about->addAuthor( ki18n( "Tobias Koenig" ), KLocalizedString(), "tokoe@kde.org" ); + KGlobal::locale()->insertCatalog(QLatin1String("libkdepim")); + setAboutData( about ); + mClientSearchConfig = new KLDAP::LdapClientSearchConfig; + initGUI(); + + connect( mHostListView, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), + this, SLOT(slotSelectionChanged(QListWidgetItem*)) ); + connect( mHostListView, SIGNAL(itemDoubleClicked(QListWidgetItem*)), + this, SLOT(slotEditHost()) ); + connect( mHostListView, SIGNAL(itemClicked(QListWidgetItem*)), + this, SLOT(slotItemClicked(QListWidgetItem*)) ); - connect( mUpButton, SIGNAL(clicked()), this, SLOT(slotMoveUp()) ); - connect( mDownButton, SIGNAL(clicked()), this, SLOT(slotMoveDown()) ); + connect( mUpButton, SIGNAL(clicked()), this, SLOT(slotMoveUp()) ); + connect( mDownButton, SIGNAL(clicked()), this, SLOT(slotMoveDown()) ); } KCMLdap::~KCMLdap() @@ -115,54 +115,54 @@ void KCMLdap::slotSelectionChanged( QListWidgetItem *item ) { - bool state = ( item != 0 ); - mEditButton->setEnabled( state ); - mRemoveButton->setEnabled( state ); - mDownButton->setEnabled( item && (mHostListView->row( item ) != (mHostListView->count() - 1)) ); - mUpButton->setEnabled( item && (mHostListView->row( item ) != 0) ); + bool state = ( item != 0 ); + mEditButton->setEnabled( state ); + mRemoveButton->setEnabled( state ); + mDownButton->setEnabled( item && (mHostListView->row( item ) != (mHostListView->count() - 1)) ); + mUpButton->setEnabled( item && (mHostListView->row( item ) != 0) ); } void KCMLdap::slotItemClicked( QListWidgetItem *item ) { - LDAPItem *ldapItem = dynamic_cast( item ); - if ( !ldapItem ) { - return; - } + LDAPItem *ldapItem = dynamic_cast( item ); + if ( !ldapItem ) { + return; + } - if ( (ldapItem->checkState() == Qt::Checked) != ldapItem->isActive() ) { - emit changed( true ); - ldapItem->setIsActive( ldapItem->checkState() == Qt::Checked ); - } + if ( (ldapItem->checkState() == Qt::Checked) != ldapItem->isActive() ) { + emit changed( true ); + ldapItem->setIsActive( ldapItem->checkState() == Qt::Checked ); + } } void KCMLdap::slotAddHost() { - KLDAP::LdapServer server; - AddHostDialog dlg( &server, dialogParent() ); + KLDAP::LdapServer server; + AddHostDialog dlg( &server, dialogParent() ); - if ( dlg.exec() && !server.host().isEmpty() ) { //krazy:exclude=crashy - new LDAPItem( mHostListView, server ); + if ( dlg.exec() && !server.host().isEmpty() ) { //krazy:exclude=crashy + new LDAPItem( mHostListView, server ); - emit changed( true ); - } + emit changed( true ); + } } void KCMLdap::slotEditHost() { - LDAPItem *item = dynamic_cast( mHostListView->currentItem() ); - if ( !item ) { - return; - } - - KLDAP::LdapServer server = item->server(); - AddHostDialog dlg( &server, dialogParent() ); - dlg.setCaption( i18n( "Edit Host" ) ); + LDAPItem *item = dynamic_cast( mHostListView->currentItem() ); + if ( !item ) { + return; + } - if ( dlg.exec() && !server.host().isEmpty() ) { //krazy:exclude=crashy - item->setServer( server ); + KLDAP::LdapServer server = item->server(); + AddHostDialog dlg( &server, dialogParent() ); + dlg.setCaption( i18n( "Edit Host" ) ); - emit changed( true ); - } + if ( dlg.exec() && !server.host().isEmpty() ) { //krazy:exclude=crashy + item->setServer( server ); + + emit changed( true ); + } } void KCMLdap::slotRemoveHost() @@ -183,187 +183,187 @@ static void swapItems( LDAPItem *item, LDAPItem *other ) { - KLDAP::LdapServer server = item->server(); - bool isActive = item->isActive(); - item->setServer( other->server() ); - item->setIsActive( other->isActive() ); - item->setCheckState( other->isActive() ? Qt::Checked : Qt::Unchecked ); - other->setServer( server ); - other->setIsActive( isActive ); - other->setCheckState( isActive ? Qt::Checked : Qt::Unchecked ); + KLDAP::LdapServer server = item->server(); + bool isActive = item->isActive(); + item->setServer( other->server() ); + item->setIsActive( other->isActive() ); + item->setCheckState( other->isActive() ? Qt::Checked : Qt::Unchecked ); + other->setServer( server ); + other->setIsActive( isActive ); + other->setCheckState( isActive ? Qt::Checked : Qt::Unchecked ); } void KCMLdap::slotMoveUp() { - const QList selectedItems = mHostListView->selectedItems(); - if ( selectedItems.count() == 0 ) { - return; - } - - LDAPItem *item = static_cast( mHostListView->selectedItems().first() ); - if ( !item ) { - return; - } - - LDAPItem *above = static_cast( mHostListView->item( mHostListView->row( item ) - 1 ) ); - if ( !above ) { - return; - } + const QList selectedItems = mHostListView->selectedItems(); + if ( selectedItems.count() == 0 ) { + return; + } - swapItems( item, above ); + LDAPItem *item = static_cast( mHostListView->selectedItems().first() ); + if ( !item ) { + return; + } - mHostListView->setCurrentItem( above ); - above->setSelected( true ); + LDAPItem *above = static_cast( mHostListView->item( mHostListView->row( item ) - 1 ) ); + if ( !above ) { + return; + } + + swapItems( item, above ); + + mHostListView->setCurrentItem( above ); + above->setSelected( true ); - emit changed( true ); + emit changed( true ); } void KCMLdap::slotMoveDown() { - const QList selectedItems = mHostListView->selectedItems(); - if ( selectedItems.count() == 0 ) { - return; - } - - LDAPItem *item = static_cast( mHostListView->selectedItems().first() ); - if ( !item ) { - return; - } - - LDAPItem *below = static_cast( mHostListView->item( mHostListView->row( item ) + 1 ) ); - if ( !below ) { - return; - } + const QList selectedItems = mHostListView->selectedItems(); + if ( selectedItems.count() == 0 ) { + return; + } - swapItems( item, below ); + LDAPItem *item = static_cast( mHostListView->selectedItems().first() ); + if ( !item ) { + return; + } - mHostListView->setCurrentItem( below ); - below->setSelected( true ); + LDAPItem *below = static_cast( mHostListView->item( mHostListView->row( item ) + 1 ) ); + if ( !below ) { + return; + } - emit changed( true ); + swapItems( item, below ); + + mHostListView->setCurrentItem( below ); + below->setSelected( true ); + + emit changed( true ); } void KCMLdap::load() { - mHostListView->clear(); - KConfig *config = KLDAP::LdapClientSearchConfig::config(); - KConfigGroup group( config, "LDAP" ); - - uint count = group.readEntry( "NumSelectedHosts", 0 ); - for ( uint i = 0; i < count; ++i ) { - KLDAP::LdapServer server; - mClientSearchConfig->readConfig( server, group, i, true ); - LDAPItem *item = new LDAPItem( mHostListView, server, true ); - item->setCheckState( Qt::Checked ); - } + mHostListView->clear(); + KConfig *config = KLDAP::LdapClientSearchConfig::config(); + KConfigGroup group( config, "LDAP" ); + + uint count = group.readEntry( "NumSelectedHosts", 0 ); + for ( uint i = 0; i < count; ++i ) { + KLDAP::LdapServer server; + mClientSearchConfig->readConfig( server, group, i, true ); + LDAPItem *item = new LDAPItem( mHostListView, server, true ); + item->setCheckState( Qt::Checked ); + } - count = group.readEntry( "NumHosts", 0 ); - for ( uint i = 0; i < count; ++i ) { - KLDAP::LdapServer server; - mClientSearchConfig->readConfig( server, group, i, false ); - new LDAPItem( mHostListView, server ); - } + count = group.readEntry( "NumHosts", 0 ); + for ( uint i = 0; i < count; ++i ) { + KLDAP::LdapServer server; + mClientSearchConfig->readConfig( server, group, i, false ); + new LDAPItem( mHostListView, server ); + } - emit changed( false ); + emit changed( false ); } void KCMLdap::save() { - KConfig *config = KLDAP::LdapClientSearchConfig::config(); - config->deleteGroup( "LDAP" ); + KConfig *config = KLDAP::LdapClientSearchConfig::config(); + config->deleteGroup( "LDAP" ); - KConfigGroup group( config, "LDAP" ); + KConfigGroup group( config, "LDAP" ); - uint selected = 0; - uint unselected = 0; - for ( int i = 0; i < mHostListView->count(); ++i ) { - LDAPItem *item = dynamic_cast( mHostListView->item( i ) ); - if ( !item ) { - continue; + uint selected = 0; + uint unselected = 0; + for ( int i = 0; i < mHostListView->count(); ++i ) { + LDAPItem *item = dynamic_cast( mHostListView->item( i ) ); + if ( !item ) { + continue; + } + + KLDAP::LdapServer server = item->server(); + if ( item->checkState() == Qt::Checked ) { + mClientSearchConfig->writeConfig( server, group, selected, true ); + selected++; + } else { + mClientSearchConfig->writeConfig( server, group, unselected, false ); + unselected++; + } } - KLDAP::LdapServer server = item->server(); - if ( item->checkState() == Qt::Checked ) { - mClientSearchConfig->writeConfig( server, group, selected, true ); - selected++; - } else { - mClientSearchConfig->writeConfig( server, group, unselected, false ); - unselected++; - } - } - - group.writeEntry( "NumSelectedHosts", selected ); - group.writeEntry( "NumHosts", unselected ); - config->sync(); + group.writeEntry( "NumSelectedHosts", selected ); + group.writeEntry( "NumHosts", unselected ); + config->sync(); - emit changed( false ); + emit changed( false ); } void KCMLdap::defaults() { - // add default configuration here + // add default configuration here } void KCMLdap::initGUI() { - QVBoxLayout *layout = new QVBoxLayout; - layout->setSpacing( KDialog::spacingHint() ); - layout->setMargin( 0 ); - setLayout(layout); - - QGroupBox *groupBox = new QGroupBox( i18n( "LDAP Servers" ), this ); - QVBoxLayout *mainLayout = new QVBoxLayout( groupBox ); - - // Contents of the QVGroupBox: label and hbox - QLabel *label = new QLabel( i18n( "Check all servers that should be used:" ) ); - mainLayout->addWidget( label ); - - KHBox *hBox = new KHBox; - hBox->setSpacing( 6 ); - mainLayout->addWidget(hBox); - // Contents of the hbox: listview and up/down buttons on the right (vbox) - mHostListView = new QListWidget( hBox ); - mHostListView->setSortingEnabled( false ); - - KVBox *upDownBox = new KVBox( hBox ); - upDownBox->setSpacing( 6 ); - mUpButton = new QToolButton( upDownBox ); - mUpButton->setIcon( KIcon( QLatin1String("go-up") ) ); - mUpButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); - mUpButton->setEnabled( false ); // b/c no item is selected yet - - mDownButton = new QToolButton( upDownBox ); - mDownButton->setIcon( KIcon( QLatin1String("go-down") ) ); - mDownButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); - mDownButton->setEnabled( false ); // b/c no item is selected yet - - QWidget *spacer = new QWidget( upDownBox ); - upDownBox->setStretchFactor( spacer, 100 ); - - layout->addWidget( groupBox ); - - KDialogButtonBox *buttons = new KDialogButtonBox( this ); - buttons->addButton( i18n( "&Add Host..." ), - QDialogButtonBox::ActionRole, this, SLOT(slotAddHost()) ); - mEditButton = buttons->addButton( i18n( "&Edit Host..." ), - QDialogButtonBox::ActionRole, this, SLOT(slotEditHost()) ); - mEditButton->setEnabled( false ); - mRemoveButton = buttons->addButton( i18n( "&Remove Host" ), - QDialogButtonBox::ActionRole, this, SLOT(slotRemoveHost()) ); - mRemoveButton->setEnabled( false ); - buttons->layout(); + QVBoxLayout *layout = new QVBoxLayout; + layout->setSpacing( KDialog::spacingHint() ); + layout->setMargin( 0 ); + setLayout(layout); + + QGroupBox *groupBox = new QGroupBox( i18n( "LDAP Servers" ), this ); + QVBoxLayout *mainLayout = new QVBoxLayout( groupBox ); + + // Contents of the QVGroupBox: label and hbox + QLabel *label = new QLabel( i18n( "Check all servers that should be used:" ) ); + mainLayout->addWidget( label ); + + KHBox *hBox = new KHBox; + hBox->setSpacing( 6 ); + mainLayout->addWidget(hBox); + // Contents of the hbox: listview and up/down buttons on the right (vbox) + mHostListView = new QListWidget( hBox ); + mHostListView->setSortingEnabled( false ); + + KVBox *upDownBox = new KVBox( hBox ); + upDownBox->setSpacing( 6 ); + mUpButton = new QToolButton( upDownBox ); + mUpButton->setIcon( KIcon( QLatin1String("go-up") ) ); + mUpButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); + mUpButton->setEnabled( false ); // b/c no item is selected yet + + mDownButton = new QToolButton( upDownBox ); + mDownButton->setIcon( KIcon( QLatin1String("go-down") ) ); + mDownButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); + mDownButton->setEnabled( false ); // b/c no item is selected yet + + QWidget *spacer = new QWidget( upDownBox ); + upDownBox->setStretchFactor( spacer, 100 ); + + layout->addWidget( groupBox ); + + KDialogButtonBox *buttons = new KDialogButtonBox( this ); + buttons->addButton( i18n( "&Add Host..." ), + QDialogButtonBox::ActionRole, this, SLOT(slotAddHost()) ); + mEditButton = buttons->addButton( i18n( "&Edit Host..." ), + QDialogButtonBox::ActionRole, this, SLOT(slotEditHost()) ); + mEditButton->setEnabled( false ); + mRemoveButton = buttons->addButton( i18n( "&Remove Host" ), + QDialogButtonBox::ActionRole, this, SLOT(slotRemoveHost()) ); + mRemoveButton->setEnabled( false ); + buttons->layout(); - layout->addWidget( buttons ); + layout->addWidget( buttons ); - resize( QSize( 460, 300 ).expandedTo( sizeHint() ) ); + resize( QSize( 460, 300 ).expandedTo( sizeHint() ) ); } QWidget* KCMLdap::dialogParent() { #ifdef Q_WS_MAEMO_5 - return 0; + return 0; #else - return this; + return this; #endif } diff -Nru kdepim-4.12.97/libkdepim/ldap/ldapclient.cpp kdepim-4.13.0/libkdepim/ldap/ldapclient.cpp --- kdepim-4.12.97/libkdepim/ldap/ldapclient.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/ldap/ldapclient.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -45,21 +45,21 @@ class LdapClient::Private { - public: +public: Private( LdapClient *qq ) - : q( qq ), - mJob( 0 ), - mActive( false ), - mSession( 0 ) + : q( qq ), + mJob( 0 ), + mActive( false ), + mSession( 0 ) { } ~Private() { - q->cancelQuery(); + q->cancelQuery(); #ifdef KDEPIM_INPROCESS_LDAP - mSession->disconnectAndDelete(); - mSession = 0; + mSession->disconnectAndDelete(); + mSession = 0; #endif } @@ -91,130 +91,130 @@ }; LdapClient::LdapClient( int clientNumber, QObject *parent ) - : QObject( parent ), d( new Private( this ) ) + : QObject( parent ), d( new Private( this ) ) { - d->mClientNumber = clientNumber; - d->mCompletionWeight = 50 - d->mClientNumber; + d->mClientNumber = clientNumber; + d->mCompletionWeight = 50 - d->mClientNumber; } LdapClient::~LdapClient() { - delete d; + delete d; } bool LdapClient::isActive() const { - return d->mActive; + return d->mActive; } void LdapClient::setServer( const KLDAP::LdapServer &server ) { - d->mServer = server; + d->mServer = server; #ifdef KDEPIM_INPROCESS_LDAP - if ( !d->mSession ) - d->mSession = new LdapSession( this ); - d->mSession->connectToServer( server ); + if ( !d->mSession ) + d->mSession = new LdapSession( this ); + d->mSession->connectToServer( server ); #endif } const KLDAP::LdapServer LdapClient::server() const { - return d->mServer; + return d->mServer; } void LdapClient::setAttributes( const QStringList &attrs ) { - d->mAttrs = attrs; - d->mAttrs << QLatin1String("objectClass"); // via objectClass we detect distribution lists + d->mAttrs = attrs; + d->mAttrs << QLatin1String("objectClass"); // via objectClass we detect distribution lists } QStringList LdapClient::attributes() const { - return d->mAttrs; + return d->mAttrs; } void LdapClient::setScope( const QString scope ) { - d->mScope = scope; + d->mScope = scope; } void LdapClient::startQuery( const QString &filter ) { - cancelQuery(); - KLDAP::LdapUrl url; + cancelQuery(); + KLDAP::LdapUrl url; - url = d->mServer.url(); + url = d->mServer.url(); - url.setAttributes( d->mAttrs ); - url.setScope( d->mScope == QLatin1String("one") ? KLDAP::LdapUrl::One : KLDAP::LdapUrl::Sub ); - url.setFilter( QLatin1Char('(') + filter + QLatin1Char(')') ); + url.setAttributes( d->mAttrs ); + url.setScope( d->mScope == QLatin1String("one") ? KLDAP::LdapUrl::One : KLDAP::LdapUrl::Sub ); + url.setFilter( QLatin1Char('(') + filter + QLatin1Char(')') ); - kDebug(5300) <<"LdapClient: Doing query:" << url.prettyUrl(); + kDebug(5300) <<"LdapClient: Doing query:" << url.prettyUrl(); - d->startParseLDIF(); - d->mActive = true; + d->startParseLDIF(); + d->mActive = true; #ifndef KDEPIM_INPROCESS_LDAP - d->mJob = KIO::get( url, KIO::NoReload, KIO::HideProgressInfo ); - connect( d->mJob, SIGNAL(data(KIO::Job*,QByteArray)), - this, SLOT(slotData(KIO::Job*,QByteArray)) ); + d->mJob = KIO::get( url, KIO::NoReload, KIO::HideProgressInfo ); + connect( d->mJob, SIGNAL(data(KIO::Job*,QByteArray)), + this, SLOT(slotData(KIO::Job*,QByteArray)) ); #else - if ( !d->mSession ) - return; - d->mJob = d->mSession->get( url ); - connect( d->mJob, SIGNAL(data(QByteArray)), - this, SLOT(slotData(QByteArray)) ); + if ( !d->mSession ) + return; + d->mJob = d->mSession->get( url ); + connect( d->mJob, SIGNAL(data(QByteArray)), + this, SLOT(slotData(QByteArray)) ); #endif - connect( d->mJob, SIGNAL(infoMessage(KJob*,QString,QString)), - this, SLOT(slotInfoMessage(KJob*,QString,QString)) ); - connect( d->mJob, SIGNAL(result(KJob*)), - this, SLOT(slotDone()) ); + connect( d->mJob, SIGNAL(infoMessage(KJob*,QString,QString)), + this, SLOT(slotInfoMessage(KJob*,QString,QString)) ); + connect( d->mJob, SIGNAL(result(KJob*)), + this, SLOT(slotDone()) ); } void LdapClient::cancelQuery() { - if ( d->mJob ) { - d->mJob->kill(); - d->mJob = 0; - } + if ( d->mJob ) { + d->mJob->kill(); + d->mJob = 0; + } - d->mActive = false; + d->mActive = false; } void LdapClient::Private::slotData( KIO::Job*, const QByteArray &data ) { - parseLDIF( data ); + parseLDIF( data ); } void LdapClient::Private::slotData( const QByteArray &data ) { - parseLDIF( data ); + parseLDIF( data ); } void LdapClient::Private::slotInfoMessage( KJob*, const QString&, const QString& ) { - //qDebug("Job said \"%s\"", info.toLatin1()); + //qDebug("Job said \"%s\"", info.toLatin1()); } void LdapClient::Private::slotDone() { - endParseLDIF(); - mActive = false; - if ( !mJob ) - return; - int err = mJob->error(); - if ( err && err != KIO::ERR_USER_CANCELED ) { - emit q->error( mJob->errorString() ); - } + endParseLDIF(); + mActive = false; + if ( !mJob ) + return; + int err = mJob->error(); + if ( err && err != KIO::ERR_USER_CANCELED ) { + emit q->error( mJob->errorString() ); + } #ifdef KDEPIM_INPROCESS_LDAP - QMetaObject::invokeMethod( mJob, "deleteLater", Qt::QueuedConnection ); // it's in a different thread + QMetaObject::invokeMethod( mJob, "deleteLater", Qt::QueuedConnection ); // it's in a different thread #endif - emit q->done(); + emit q->done(); } void LdapClient::Private::startParseLDIF() { - mCurrentObject.clear(); - mLdif.startParsing(); + mCurrentObject.clear(); + mLdif.startParsing(); } void LdapClient::Private::endParseLDIF() @@ -223,100 +223,100 @@ void LdapClient::Private::finishCurrentObject() { - mCurrentObject.setDn( mLdif.dn() ); - KLDAP::LdapAttrValue objectclasses; - KLDAP::LdapAttrMap::ConstIterator end = mCurrentObject.attributes().constEnd(); - for ( KLDAP::LdapAttrMap::ConstIterator it = mCurrentObject.attributes().constBegin(); - it != end; ++it ) { - - if ( it.key().toLower() == QLatin1String("objectclass") ) { - objectclasses = it.value(); - break; + mCurrentObject.setDn( mLdif.dn() ); + KLDAP::LdapAttrValue objectclasses; + KLDAP::LdapAttrMap::ConstIterator end = mCurrentObject.attributes().constEnd(); + for ( KLDAP::LdapAttrMap::ConstIterator it = mCurrentObject.attributes().constBegin(); + it != end; ++it ) { + + if ( it.key().toLower() == QLatin1String("objectclass") ) { + objectclasses = it.value(); + break; + } } - } - bool groupofnames = false; - KLDAP::LdapAttrValue::ConstIterator endValue(objectclasses.constEnd()); - for ( KLDAP::LdapAttrValue::ConstIterator it = objectclasses.constBegin(); - it != endValue; ++it ) { - - QByteArray sClass = (*it).toLower(); - if ( sClass == "groupofnames" || sClass == "kolabgroupofnames" ) { - groupofnames = true; + bool groupofnames = false; + KLDAP::LdapAttrValue::ConstIterator endValue(objectclasses.constEnd()); + for ( KLDAP::LdapAttrValue::ConstIterator it = objectclasses.constBegin(); + it != endValue; ++it ) { + + const QByteArray sClass = (*it).toLower(); + if ( sClass == "groupofnames" || sClass == "kolabgroupofnames" ) { + groupofnames = true; + } } - } - if ( groupofnames ) { - KLDAP::LdapAttrMap::ConstIterator it = mCurrentObject.attributes().find( QLatin1String("mail") ); - if ( it == mCurrentObject.attributes().end() ) { - // No explicit mail address found so far? - // Fine, then we use the address stored in the DN. - QString sMail; - QStringList lMail = mCurrentObject.dn().toString().split( QLatin1String(",dc="), QString::SkipEmptyParts ); - const int n = lMail.count(); - if ( n ) { - if ( lMail.first().toLower().startsWith( QLatin1String( "cn=" ) ) ) { - sMail = lMail.first().simplified().mid( 3 ); - if ( 1 < n ) { - sMail.append( QLatin1Char('@') ); - } - for ( int i = 1; i < n; ++i ) { - sMail.append( lMail.at(i) ); - if ( i < n - 1 ) { - sMail.append( QLatin1Char('.') ); + if ( groupofnames ) { + KLDAP::LdapAttrMap::ConstIterator it = mCurrentObject.attributes().find( QLatin1String("mail") ); + if ( it == mCurrentObject.attributes().end() ) { + // No explicit mail address found so far? + // Fine, then we use the address stored in the DN. + QString sMail; + const QStringList lMail = mCurrentObject.dn().toString().split( QLatin1String(",dc="), QString::SkipEmptyParts ); + const int n = lMail.count(); + if ( n ) { + if ( lMail.first().toLower().startsWith( QLatin1String( "cn=" ) ) ) { + sMail = lMail.first().simplified().mid( 3 ); + if ( 1 < n ) { + sMail.append( QLatin1Char('@') ); + } + for ( int i = 1; i < n; ++i ) { + sMail.append( lMail.at(i) ); + if ( i < n - 1 ) { + sMail.append( QLatin1Char('.') ); + } + } + mCurrentObject.addValue( QLatin1String("mail"), sMail.toUtf8() ); + } } - } - mCurrentObject.addValue( QLatin1String("mail"), sMail.toUtf8() ); } - } } - } - emit q->result( *q, mCurrentObject ); - mCurrentObject.clear(); + emit q->result( *q, mCurrentObject ); + mCurrentObject.clear(); } void LdapClient::Private::parseLDIF( const QByteArray &data ) { - //kDebug(5300) <<"LdapClient::parseLDIF(" << QCString(data.data(), data.size()+1) <<" )"; - if ( data.size() ) { - mLdif.setLdif( data ); - } else { - mLdif.endLdif(); - } - KLDAP::Ldif::ParseValue ret; - QString name; - do { - ret = mLdif.nextItem(); - switch ( ret ) { - case KLDAP::Ldif::Item: + //kDebug(5300) <<"LdapClient::parseLDIF(" << QCString(data.data(), data.size()+1) <<" )"; + if ( data.size() ) { + mLdif.setLdif( data ); + } else { + mLdif.endLdif(); + } + KLDAP::Ldif::ParseValue ret; + QString name; + do { + ret = mLdif.nextItem(); + switch ( ret ) { + case KLDAP::Ldif::Item: { - name = mLdif.attr(); - QByteArray value = mLdif.value(); - mCurrentObject.addValue( name, value ); + name = mLdif.attr(); + const QByteArray value = mLdif.value(); + mCurrentObject.addValue( name, value ); } - break; - case KLDAP::Ldif::EndEntry: - finishCurrentObject(); - break; - default: - break; - } - } while ( ret != KLDAP::Ldif::MoreData ); + break; + case KLDAP::Ldif::EndEntry: + finishCurrentObject(); + break; + default: + break; + } + } while ( ret != KLDAP::Ldif::MoreData ); } int LdapClient::clientNumber() const { - return d->mClientNumber; + return d->mClientNumber; } int LdapClient::completionWeight() const { - return d->mCompletionWeight; + return d->mCompletionWeight; } void LdapClient::setCompletionWeight( int weight ) { - d->mCompletionWeight = weight; + d->mCompletionWeight = weight; } diff -Nru kdepim-4.12.97/libkdepim/ldap/ldapclient.h kdepim-4.13.0/libkdepim/ldap/ldapclient.h --- kdepim-4.12.97/libkdepim/ldap/ldapclient.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/ldap/ldapclient.h 2014-04-10 07:40:20.000000000 +0000 @@ -45,9 +45,9 @@ */ class KDEPIM_EXPORT LdapClient : public QObject { - Q_OBJECT + Q_OBJECT - public: +public: /** * Creates a new ldap client. * @@ -128,7 +128,7 @@ */ void cancelQuery(); - Q_SIGNALS: +Q_SIGNALS: /** * This signal is emitted when the query has finished. */ @@ -147,7 +147,7 @@ */ void result( const KLDAP::LdapClient &client, const KLDAP::LdapObject& ); - private: +private: //@cond PRIVATE class Private; Private* const d; diff -Nru kdepim-4.12.97/libkdepim/ldap/ldapclientsearchconfig.cpp kdepim-4.13.0/libkdepim/ldap/ldapclientsearchconfig.cpp --- kdepim-4.12.97/libkdepim/ldap/ldapclientsearchconfig.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/ldap/ldapclientsearchconfig.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -55,7 +55,7 @@ KConfig* LdapClientSearchConfig::config() { - return s_config; + return s_config; } LdapClientSearchConfig::LdapClientSearchConfig(QObject *parent) diff -Nru kdepim-4.12.97/libkdepim/ldap/ldapclientsearch.cpp kdepim-4.13.0/libkdepim/ldap/ldapclientsearch.cpp --- kdepim-4.12.97/libkdepim/ldap/ldapclientsearch.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/ldap/ldapclientsearch.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -51,7 +51,7 @@ class LdapClientSearch::Private { - public: +public: Private( LdapClientSearch *qq ) : q( qq ), mActiveClients( 0 ), @@ -66,8 +66,8 @@ } struct ResultObject { - const LdapClient *client; - KLDAP::LdapObject object; + const LdapClient *client; + KLDAP::LdapObject object; }; void readWeighForClient( LdapClient *client, const KConfigGroup &config, int clientNumber ); @@ -93,117 +93,117 @@ }; LdapClientSearch::LdapClientSearch( QObject *parent ) - : QObject( parent ), d( new Private( this ) ) + : QObject( parent ), d( new Private( this ) ) { - if ( !KProtocolInfo::isKnownProtocol( KUrl( "ldap://localhost" ) ) ) { - d->mNoLDAPLookup = true; - return; - } - - d->readConfig(); - connect( KDirWatch::self(), SIGNAL(dirty(QString)), this, - SLOT(slotFileChanged(QString)) ); + if ( !KProtocolInfo::isKnownProtocol( KUrl( "ldap://localhost" ) ) ) { + d->mNoLDAPLookup = true; + return; + } + + d->readConfig(); + connect( KDirWatch::self(), SIGNAL(dirty(QString)), this, + SLOT(slotFileChanged(QString)) ); } LdapClientSearch::~LdapClientSearch() { - delete d; + delete d; } void LdapClientSearch::Private::readWeighForClient( LdapClient *client, const KConfigGroup &config, int clientNumber ) { - const int completionWeight = config.readEntry( QString::fromLatin1( "SelectedCompletionWeight%1" ).arg( clientNumber ), -1 ); - if ( completionWeight != -1 ) { - client->setCompletionWeight( completionWeight ); - } + const int completionWeight = config.readEntry( QString::fromLatin1( "SelectedCompletionWeight%1" ).arg( clientNumber ), -1 ); + if ( completionWeight != -1 ) { + client->setCompletionWeight( completionWeight ); + } } void LdapClientSearch::updateCompletionWeights() { - KConfigGroup config( KLDAP::LdapClientSearchConfig::config(), "LDAP" ); - for ( int i = 0; i < d->mClients.size(); ++i ) { - d->readWeighForClient( d->mClients[ i ], config, i ); - } + KConfigGroup config( KLDAP::LdapClientSearchConfig::config(), "LDAP" ); + for ( int i = 0; i < d->mClients.size(); ++i ) { + d->readWeighForClient( d->mClients[ i ], config, i ); + } } QList LdapClientSearch::clients() const { - return d->mClients; + return d->mClients; } void LdapClientSearch::Private::readConfig() { - q->cancelSearch(); - qDeleteAll( mClients ); - mClients.clear(); - - // stolen from KAddressBook - KConfigGroup config( KLDAP::LdapClientSearchConfig::config(), "LDAP" ); - const int numHosts = config.readEntry( "NumSelectedHosts", 0 ); - if ( !numHosts ) { - mNoLDAPLookup = true; - } else { - for ( int j = 0; j < numHosts; ++j ) { - LdapClient *ldapClient = new LdapClient( j, q ); - KLDAP::LdapServer server; - mClientSearchConfig->readConfig( server, config, j, true ); - if ( !server.host().isEmpty() ) { - mNoLDAPLookup = false; - } - ldapClient->setServer( server ); - - readWeighForClient( ldapClient, config, j ); - - QStringList attrs; - attrs << QLatin1String("cn") << QLatin1String("mail") << QLatin1String("givenname") << QLatin1String("sn"); - ldapClient->setAttributes( attrs ); - - q->connect( ldapClient, SIGNAL(result(KLDAP::LdapClient,KLDAP::LdapObject)), - q, SLOT(slotLDAPResult(KLDAP::LdapClient,KLDAP::LdapObject)) ); - q->connect( ldapClient, SIGNAL(done()), - q, SLOT(slotLDAPDone()) ); - q->connect( ldapClient, SIGNAL(error(QString)), - q, SLOT(slotLDAPError(QString)) ); - - mClients.append( ldapClient ); - } - - q->connect( &mDataTimer, SIGNAL(timeout()), SLOT(slotDataTimer()) ); - } - mConfigFile = KStandardDirs::locateLocal( "config", QLatin1String("kabldaprc") ); - KDirWatch::self()->addFile( mConfigFile ); + q->cancelSearch(); + qDeleteAll( mClients ); + mClients.clear(); + + // stolen from KAddressBook + KConfigGroup config( KLDAP::LdapClientSearchConfig::config(), "LDAP" ); + const int numHosts = config.readEntry( "NumSelectedHosts", 0 ); + if ( !numHosts ) { + mNoLDAPLookup = true; + } else { + for ( int j = 0; j < numHosts; ++j ) { + LdapClient *ldapClient = new LdapClient( j, q ); + KLDAP::LdapServer server; + mClientSearchConfig->readConfig( server, config, j, true ); + if ( !server.host().isEmpty() ) { + mNoLDAPLookup = false; + } + ldapClient->setServer( server ); + + readWeighForClient( ldapClient, config, j ); + + QStringList attrs; + attrs << QLatin1String("cn") << QLatin1String("mail") << QLatin1String("givenname") << QLatin1String("sn"); + ldapClient->setAttributes( attrs ); + + q->connect( ldapClient, SIGNAL(result(KLDAP::LdapClient,KLDAP::LdapObject)), + q, SLOT(slotLDAPResult(KLDAP::LdapClient,KLDAP::LdapObject)) ); + q->connect( ldapClient, SIGNAL(done()), + q, SLOT(slotLDAPDone()) ); + q->connect( ldapClient, SIGNAL(error(QString)), + q, SLOT(slotLDAPError(QString)) ); + + mClients.append( ldapClient ); + } + + q->connect( &mDataTimer, SIGNAL(timeout()), SLOT(slotDataTimer()) ); + } + mConfigFile = KStandardDirs::locateLocal( "config", QLatin1String("kabldaprc") ); + KDirWatch::self()->addFile( mConfigFile ); } void LdapClientSearch::Private::slotFileChanged( const QString &file ) { - if ( file == mConfigFile ) { - readConfig(); - } + if ( file == mConfigFile ) { + readConfig(); + } } void LdapClientSearch::startSearch( const QString &txt ) { - if ( d->mNoLDAPLookup ) { - return; - } - - cancelSearch(); - - int pos = txt.indexOf( QLatin1Char('\"') ); - if ( pos >= 0 ) { - ++pos; - const int pos2 = txt.indexOf( QLatin1Char('\"'), pos ); - if ( pos2 >= 0 ) { - d->mSearchText = txt.mid( pos, pos2 - pos ); + if ( d->mNoLDAPLookup ) { + return; + } + + cancelSearch(); + + int pos = txt.indexOf( QLatin1Char('\"') ); + if ( pos >= 0 ) { + ++pos; + const int pos2 = txt.indexOf( QLatin1Char('\"'), pos ); + if ( pos2 >= 0 ) { + d->mSearchText = txt.mid( pos, pos2 - pos ); + } else { + d->mSearchText = txt.mid( pos ); + } } else { - d->mSearchText = txt.mid( pos ); + d->mSearchText = txt; } - } else { - d->mSearchText = txt; - } - /* The reasoning behind this filter is: + /* The reasoning behind this filter is: * If it's a person, or a distlist, show it, even if it doesn't have an email address. * If it's not a person, or a distlist, only show it if it has an email attribute. * This allows both resource accounts with an email address which are not a person and @@ -211,192 +211,192 @@ * like structural entries in the ldap tree. */ #if 0 - const QString filter = QString::fromLatin1( "&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))" - "(|(cn=%1*)(mail=%1*)(mail=*@%1*)(givenName=%1*)(sn=%1*))" ).arg( d->mSearchText ); + const QString filter = QString::fromLatin1( "&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))" + "(|(cn=%1*)(mail=%1*)(mail=*@%1*)(givenName=%1*)(sn=%1*))" ).arg( d->mSearchText ); #endif - //Fix bug 323272 "Exchange doesn't like any queries beginning with *." - const QString filter = QString::fromLatin1( "&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))" - "(|(cn=%1*)(mail=%1*)(givenName=%1*)(sn=%1*))" ).arg( d->mSearchText ); - - QList::Iterator it; - QList::Iterator end(d->mClients.end()); - for ( it = d->mClients.begin(); it != end; ++it ) { - (*it)->startQuery( filter ); - kDebug(5300) <<"LdapClientSearch::startSearch()" << filter; - ++d->mActiveClients; - } + //Fix bug 323272 "Exchange doesn't like any queries beginning with *." + const QString filter = QString::fromLatin1( "&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))" + "(|(cn=%1*)(mail=%1*)(givenName=%1*)(sn=%1*))" ).arg( d->mSearchText ); + + QList::Iterator it; + QList::Iterator end(d->mClients.end()); + for ( it = d->mClients.begin(); it != end; ++it ) { + (*it)->startQuery( filter ); + kDebug(5300) <<"LdapClientSearch::startSearch()" << filter; + ++d->mActiveClients; + } } void LdapClientSearch::cancelSearch() { - QList::Iterator it; - QList::Iterator end(d->mClients.end()); - for ( it = d->mClients.begin(); it != end; ++it ) { - (*it)->cancelQuery(); - } + QList::Iterator it; + QList::Iterator end(d->mClients.end()); + for ( it = d->mClients.begin(); it != end; ++it ) { + (*it)->cancelQuery(); + } - d->mActiveClients = 0; - d->mResults.clear(); + d->mActiveClients = 0; + d->mResults.clear(); } void LdapClientSearch::Private::slotLDAPResult( const LdapClient &client, const KLDAP::LdapObject &obj ) { - ResultObject result; - result.client = &client; - result.object = obj; - - mResults.append( result ); - if ( !mDataTimer.isActive() ) { - mDataTimer.setSingleShot( true ); - mDataTimer.start( 500 ); - } + ResultObject result; + result.client = &client; + result.object = obj; + + mResults.append( result ); + if ( !mDataTimer.isActive() ) { + mDataTimer.setSingleShot( true ); + mDataTimer.start( 500 ); + } } void LdapClientSearch::Private::slotLDAPError( const QString& ) { - slotLDAPDone(); + slotLDAPDone(); } void LdapClientSearch::Private::slotLDAPDone() { - if ( --mActiveClients > 0 ) { - return; - } + if ( --mActiveClients > 0 ) { + return; + } - finish(); + finish(); } void LdapClientSearch::Private::slotDataTimer() { - QStringList lst; - LdapResult::List reslist; - makeSearchData( lst, reslist ); - if ( !lst.isEmpty() ) { - emit q->searchData( lst ); - } - if ( !reslist.isEmpty() ) { - emit q->searchData( reslist ); - } + QStringList lst; + LdapResult::List reslist; + makeSearchData( lst, reslist ); + if ( !lst.isEmpty() ) { + emit q->searchData( lst ); + } + if ( !reslist.isEmpty() ) { + emit q->searchData( reslist ); + } } void LdapClientSearch::Private::finish() { - mDataTimer.stop(); + mDataTimer.stop(); - slotDataTimer(); // emit final bunch of data - emit q->searchDone(); + slotDataTimer(); // emit final bunch of data + emit q->searchDone(); } void LdapClientSearch::Private::makeSearchData( QStringList &ret, LdapResult::List &resList ) { - QList< ResultObject >::ConstIterator it1; - QList< ResultObject >::ConstIterator end1(mResults.constEnd()); - for ( it1 = mResults.constBegin(); it1 != end1; ++it1 ) { - QString name, mail, givenname, sn; - QStringList mails; - bool isDistributionList = false; - bool wasCN = false; - bool wasDC = false; - - //kDebug(5300) <<"\n\nLdapClientSearch::makeSearchData()"; - - KLDAP::LdapAttrMap::ConstIterator it2; - for ( it2 = (*it1).object.attributes().constBegin(); - it2 != (*it1).object.attributes().constEnd(); ++it2 ) { - QByteArray val = (*it2).first(); - int len = val.size(); - if ( len > 0 && '\0' == val[len-1] ) { - --len; - } - const QString tmp = QString::fromUtf8( val, len ); - //kDebug(5300) <<" key: \"" << it2.key() <<"\" value: \"" << tmp <<"\""; - if ( it2.key() == QLatin1String("cn") ) { - name = tmp; - if ( mail.isEmpty() ) { - mail = tmp; - } else { - if ( wasCN ) { - mail.prepend( QLatin1String(".") ); - } else { - mail.prepend( QLatin1String("@") ); - } - mail.prepend( tmp ); + QList< ResultObject >::ConstIterator it1; + QList< ResultObject >::ConstIterator end1(mResults.constEnd()); + for ( it1 = mResults.constBegin(); it1 != end1; ++it1 ) { + QString name, mail, givenname, sn; + QStringList mails; + bool isDistributionList = false; + bool wasCN = false; + bool wasDC = false; + + //kDebug(5300) <<"\n\nLdapClientSearch::makeSearchData()"; + + KLDAP::LdapAttrMap::ConstIterator it2; + for ( it2 = (*it1).object.attributes().constBegin(); + it2 != (*it1).object.attributes().constEnd(); ++it2 ) { + QByteArray val = (*it2).first(); + int len = val.size(); + if ( len > 0 && '\0' == val[len-1] ) { + --len; + } + const QString tmp = QString::fromUtf8( val, len ); + //kDebug(5300) <<" key: \"" << it2.key() <<"\" value: \"" << tmp <<"\""; + if ( it2.key() == QLatin1String("cn") ) { + name = tmp; + if ( mail.isEmpty() ) { + mail = tmp; + } else { + if ( wasCN ) { + mail.prepend( QLatin1String(".") ); + } else { + mail.prepend( QLatin1String("@") ); + } + mail.prepend( tmp ); + } + wasCN = true; + } else if ( it2.key() == QLatin1String("dc") ) { + if ( mail.isEmpty() ) { + mail = tmp; + } else { + if ( wasDC ) { + mail.append( QLatin1String(".") ); + } else { + mail.append( QLatin1String("@") ); + } + mail.append( tmp ); + } + wasDC = true; + } else if ( it2.key() == QLatin1String("mail") ) { + mail = tmp; + KLDAP::LdapAttrValue::ConstIterator it3 = it2.value().constBegin(); + for ( ; it3 != it2.value().constEnd(); ++it3 ) { + mails.append( QString::fromUtf8( (*it3).data(), (*it3).size() ) ); + } + } else if ( it2.key() == QLatin1String("givenName") ) { + givenname = tmp; + } else if ( it2.key() == QLatin1String("sn") ) { + sn = tmp; + } else if ( it2.key() == QLatin1String("objectClass") && + (tmp == QLatin1String("groupOfNames") || tmp == QLatin1String("kolabGroupOfNames")) ) { + isDistributionList = true; + } } - wasCN = true; - } else if ( it2.key() == QLatin1String("dc") ) { - if ( mail.isEmpty() ) { - mail = tmp; + + if ( mails.isEmpty() ) { + if ( !mail.isEmpty() ) { + mails.append( mail ); + } + if ( isDistributionList ) { + //kDebug(5300) <<"\n\nLdapClientSearch::makeSearchData() found a list:" << name; + ret.append( name ); + // following lines commented out for bugfixing kolab issue #177: + // + // Unlike we thought previously we may NOT append the server name here. + // + // The right server is found by the SMTP server instead: Kolab users + // must use the correct SMTP server, by definition. + // + //mail = (*it1).client->base().simplified(); + //mail.replace( ",dc=", ".", false ); + //if( mail.startsWith("dc=", false) ) + // mail.remove(0, 3); + //mail.prepend( '@' ); + //mail.prepend( name ); + //mail = name; + } else { + continue; // nothing, bad entry + } + } else if ( name.isEmpty() ) { + ret.append( mail ); } else { - if ( wasDC ) { - mail.append( QLatin1String(".") ); - } else { - mail.append( QLatin1String("@") ); - } - mail.append( tmp ); - } - wasDC = true; - } else if ( it2.key() == QLatin1String("mail") ) { - mail = tmp; - KLDAP::LdapAttrValue::ConstIterator it3 = it2.value().constBegin(); - for ( ; it3 != it2.value().constEnd(); ++it3 ) { - mails.append( QString::fromUtf8( (*it3).data(), (*it3).size() ) ); + ret.append( QString::fromLatin1( "%1 <%2>" ).arg( name ).arg( mail ) ); } - } else if ( it2.key() == QLatin1String("givenName") ) { - givenname = tmp; - } else if ( it2.key() == QLatin1String("sn") ) { - sn = tmp; - } else if ( it2.key() == QLatin1String("objectClass") && - (tmp == QLatin1String("groupOfNames") || tmp == QLatin1String("kolabGroupOfNames")) ) { - isDistributionList = true; - } - } - - if ( mails.isEmpty() ) { - if ( !mail.isEmpty() ) { - mails.append( mail ); - } - if ( isDistributionList ) { - //kDebug(5300) <<"\n\nLdapClientSearch::makeSearchData() found a list:" << name; - ret.append( name ); - // following lines commented out for bugfixing kolab issue #177: - // - // Unlike we thought previously we may NOT append the server name here. - // - // The right server is found by the SMTP server instead: Kolab users - // must use the correct SMTP server, by definition. - // - //mail = (*it1).client->base().simplified(); - //mail.replace( ",dc=", ".", false ); - //if( mail.startsWith("dc=", false) ) - // mail.remove(0, 3); - //mail.prepend( '@' ); - //mail.prepend( name ); - //mail = name; - } else { - continue; // nothing, bad entry - } - } else if ( name.isEmpty() ) { - ret.append( mail ); - } else { - ret.append( QString::fromLatin1( "%1 <%2>" ).arg( name ).arg( mail ) ); - } - LdapResult sr; - sr.clientNumber = (*it1).client->clientNumber(); - sr.completionWeight = (*it1).client->completionWeight(); - sr.name = name; - sr.email = mails; - resList.append( sr ); - } + LdapResult sr; + sr.clientNumber = (*it1).client->clientNumber(); + sr.completionWeight = (*it1).client->completionWeight(); + sr.name = name; + sr.email = mails; + resList.append( sr ); + } - mResults.clear(); + mResults.clear(); } bool LdapClientSearch::isAvailable() const { - return !d->mNoLDAPLookup; + return !d->mNoLDAPLookup; } #include "moc_ldapclientsearch.cpp" diff -Nru kdepim-4.12.97/libkdepim/ldap/ldapclientsearch.h kdepim-4.13.0/libkdepim/ldap/ldapclientsearch.h --- kdepim-4.12.97/libkdepim/ldap/ldapclientsearch.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/ldap/ldapclientsearch.h 2014-04-10 07:40:20.000000000 +0000 @@ -39,15 +39,15 @@ */ struct LdapResult { - /** + /** * A list of LdapResult objects. */ - typedef QList List; + typedef QList List; - QString name; ///< The full name of the contact. - QStringList email; ///< The list of emails of the contact. - int clientNumber; ///< The client the contact comes from (used for sorting in a ldap-only lookup). - int completionWeight; ///< The weight of the contact (used for sorting in a completion list). + QString name; ///< The full name of the contact. + QStringList email; ///< The list of emails of the contact. + int clientNumber; ///< The client the contact comes from (used for sorting in a ldap-only lookup). + int completionWeight; ///< The weight of the contact (used for sorting in a completion list). }; /** @@ -55,9 +55,9 @@ */ class KDEPIM_EXPORT LdapClientSearch : public QObject { - Q_OBJECT + Q_OBJECT - public: +public: /** * Creates a new ldap client search object. * @@ -99,7 +99,7 @@ */ QList clients() const; - Q_SIGNALS: +Q_SIGNALS: /** * This signal is emitted whenever new contacts have been found * during the lookup. @@ -122,7 +122,7 @@ */ void searchDone(); - private: +private: //@cond PRIVATE class Private; Private* const d; diff -Nru kdepim-4.12.97/libkdepim/ldap/ldapsearchdialog.cpp kdepim-4.13.0/libkdepim/ldap/ldapsearchdialog.cpp --- kdepim-4.12.97/libkdepim/ldap/ldapsearchdialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/ldap/ldapsearchdialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -61,424 +61,424 @@ static QString asUtf8( const QByteArray &val ) { - if ( val.isEmpty() ) { - return QString(); - } - - const char *data = val.data(); - - //QString::fromUtf8() bug workaround - if ( data[ val.size() - 1 ] == '\0' ) { - return QString::fromUtf8( data, val.size() - 1 ); - } else { - return QString::fromUtf8( data, val.size() ); - } + if ( val.isEmpty() ) { + return QString(); + } + + const char *data = val.data(); + + //QString::fromUtf8() bug workaround + if ( data[ val.size() - 1 ] == '\0' ) { + return QString::fromUtf8( data, val.size() - 1 ); + } else { + return QString::fromUtf8( data, val.size() ); + } } static QString join( const KLDAP::LdapAttrValue &lst, const QString &sep ) { - QString res; - bool alredy = false; - KLDAP::LdapAttrValue::ConstIterator end(lst.constEnd()); - for ( KLDAP::LdapAttrValue::ConstIterator it = lst.constBegin(); it != end; ++it ) { - if ( alredy ) { - res += sep; - } + QString res; + bool alredy = false; + KLDAP::LdapAttrValue::ConstIterator end(lst.constEnd()); + for ( KLDAP::LdapAttrValue::ConstIterator it = lst.constBegin(); it != end; ++it ) { + if ( alredy ) { + res += sep; + } - alredy = true; - res += asUtf8( *it ); - } + alredy = true; + res += asUtf8( *it ); + } - return res; + return res; } static QMap& adrbookattr2ldap() { - static QMap keys; + static QMap keys; - if ( keys.isEmpty() ) { - keys[ i18nc( "@item LDAP search key", "Title" ) ] = QLatin1String("title"); - keys[ i18n( "Full Name" ) ] = QLatin1String("cn"); - keys[ i18nc( "@item LDAP search key", "Email" ) ] = QLatin1String("mail"); - keys[ i18n( "Home Number" ) ] = QLatin1String("homePhone"); - keys[ i18n( "Work Number" ) ] = QLatin1String("telephoneNumber"); - keys[ i18n( "Mobile Number" ) ] = QLatin1String("mobile"); - keys[ i18n( "Fax Number" ) ] = QLatin1String("facsimileTelephoneNumber"); - keys[ i18n( "Pager" ) ] = QLatin1String("pager"); - keys[ i18n( "Street" ) ] = QLatin1String("street"); - keys[ i18nc( "@item LDAP search key", "State" ) ] = QLatin1String("st"); - keys[ i18n( "Country" ) ] = QLatin1String("co"); - keys[ i18n( "City" ) ] = QLatin1String("l"); //krazy:exclude=doublequote_chars - keys[ i18n( "Organization" ) ] = QLatin1String("o"); //krazy:exclude=doublequote_chars - keys[ i18n( "Company" ) ] = QLatin1String("Company"); - keys[ i18n( "Department" ) ] = QLatin1String("department"); - keys[ i18n( "Zip Code" ) ] = QLatin1String("postalCode"); - keys[ i18n( "Postal Address" ) ] = QLatin1String("postalAddress"); - keys[ i18n( "Description" ) ] = QLatin1String("description"); - keys[ i18n( "User ID" ) ] = QLatin1String("uid"); - } + if ( keys.isEmpty() ) { + keys[ i18nc( "@item LDAP search key", "Title" ) ] = QLatin1String("title"); + keys[ i18n( "Full Name" ) ] = QLatin1String("cn"); + keys[ i18nc( "@item LDAP search key", "Email" ) ] = QLatin1String("mail"); + keys[ i18n( "Home Number" ) ] = QLatin1String("homePhone"); + keys[ i18n( "Work Number" ) ] = QLatin1String("telephoneNumber"); + keys[ i18n( "Mobile Number" ) ] = QLatin1String("mobile"); + keys[ i18n( "Fax Number" ) ] = QLatin1String("facsimileTelephoneNumber"); + keys[ i18n( "Pager" ) ] = QLatin1String("pager"); + keys[ i18n( "Street" ) ] = QLatin1String("street"); + keys[ i18nc( "@item LDAP search key", "State" ) ] = QLatin1String("st"); + keys[ i18n( "Country" ) ] = QLatin1String("co"); + keys[ i18n( "City" ) ] = QLatin1String("l"); //krazy:exclude=doublequote_chars + keys[ i18n( "Organization" ) ] = QLatin1String("o"); //krazy:exclude=doublequote_chars + keys[ i18n( "Company" ) ] = QLatin1String("Company"); + keys[ i18n( "Department" ) ] = QLatin1String("department"); + keys[ i18n( "Zip Code" ) ] = QLatin1String("postalCode"); + keys[ i18n( "Postal Address" ) ] = QLatin1String("postalAddress"); + keys[ i18n( "Description" ) ] = QLatin1String("description"); + keys[ i18n( "User ID" ) ] = QLatin1String("uid"); + } - return keys; + return keys; } static QString makeFilter( const QString &query, const QString &attr, bool startsWith ) { - /* The reasoning behind this filter is: + /* The reasoning behind this filter is: * If it's a person, or a distlist, show it, even if it doesn't have an email address. * If it's not a person, or a distlist, only show it if it has an email attribute. * This allows both resource accounts with an email address which are not a person and * person entries without an email address to show up, while still not showing things * like structural entries in the ldap tree. */ - QString result( QLatin1String("&(|(objectclass=person)(objectclass=groupofnames)(mail=*))(") ); - if ( query.isEmpty() ) { - // Return a filter that matches everything - return result + QLatin1String("|(cn=*)(sn=*)") + QLatin1Char(')'); - } - - if ( attr == i18nc( "Search attribute: Name of contact", "Name" ) ) { - result += startsWith ? QLatin1String("|(cn=%1*)(sn=%2*)") : QLatin1String("|(cn=*%1*)(sn=*%2*)"); - result = result.arg( query ).arg( query ); - } else { - result += startsWith ? QLatin1String("%1=%2*") : QLatin1String("%1=*%2*"); - if ( attr == i18nc( "Search attribute: Email of the contact", "Email" ) ) { - result = result.arg( QLatin1String("mail") ).arg( query ); - } else if ( attr == i18n( "Home Number" ) ) { - result = result.arg( QLatin1String("homePhone") ).arg( query ); - } else if ( attr == i18n( "Work Number" ) ) { - result = result.arg( QLatin1String("telephoneNumber") ).arg( query ); + QString result( QLatin1String("&(|(objectclass=person)(objectclass=groupofnames)(mail=*))(") ); + if ( query.isEmpty() ) { + // Return a filter that matches everything + return result + QLatin1String("|(cn=*)(sn=*)") + QLatin1Char(')'); + } + + if ( attr == i18nc( "Search attribute: Name of contact", "Name" ) ) { + result += startsWith ? QLatin1String("|(cn=%1*)(sn=%2*)") : QLatin1String("|(cn=*%1*)(sn=*%2*)"); + result = result.arg( query ).arg( query ); } else { - // Error? - result.clear(); - return result; - } - } - result += QLatin1Char(')'); - return result; + result += startsWith ? QLatin1String("%1=%2*") : QLatin1String("%1=*%2*"); + if ( attr == i18nc( "Search attribute: Email of the contact", "Email" ) ) { + result = result.arg( QLatin1String("mail") ).arg( query ); + } else if ( attr == i18n( "Home Number" ) ) { + result = result.arg( QLatin1String("homePhone") ).arg( query ); + } else if ( attr == i18n( "Work Number" ) ) { + result = result.arg( QLatin1String("telephoneNumber") ).arg( query ); + } else { + // Error? + result.clear(); + return result; + } + } + result += QLatin1Char(')'); + return result; } static KABC::Addressee convertLdapAttributesToAddressee( const KLDAP::LdapAttrMap &attrs ) { - KABC::Addressee addr; + KABC::Addressee addr; + + // name + if ( !attrs.value( QLatin1String("cn") ).isEmpty() ) { + addr.setNameFromString( asUtf8( attrs[QLatin1String("cn")].first() ) ); + } + + // email + KLDAP::LdapAttrValue lst = attrs[QLatin1String("mail")]; + KLDAP::LdapAttrValue::ConstIterator it = lst.constBegin(); + bool pref = true; + while ( it != lst.constEnd() ) { + addr.insertEmail( asUtf8( *it ), pref ); + pref = false; + ++it; + } + + if ( !attrs.value( QLatin1String("o") ).isEmpty() ) { + addr.setOrganization( asUtf8( attrs[ QLatin1String("o") ].first() ) ); + } + if ( addr.organization().isEmpty() && !attrs.value( QLatin1String("Company") ).isEmpty() ) { + addr.setOrganization( asUtf8( attrs[ QLatin1String("Company") ].first() ) ); + } - // name - if ( !attrs.value( QLatin1String("cn") ).isEmpty() ) { - addr.setNameFromString( asUtf8( attrs[QLatin1String("cn")].first() ) ); - } - - // email - KLDAP::LdapAttrValue lst = attrs[QLatin1String("mail")]; - KLDAP::LdapAttrValue::ConstIterator it = lst.constBegin(); - bool pref = true; - while ( it != lst.constEnd() ) { - addr.insertEmail( asUtf8( *it ), pref ); - pref = false; - ++it; - } - - if ( !attrs.value( QLatin1String("o") ).isEmpty() ) { - addr.setOrganization( asUtf8( attrs[ QLatin1String("o") ].first() ) ); - } - if ( addr.organization().isEmpty() && !attrs.value( QLatin1String("Company") ).isEmpty() ) { - addr.setOrganization( asUtf8( attrs[ QLatin1String("Company") ].first() ) ); - } - - // Address - KABC::Address workAddr( KABC::Address::Work ); - - if ( !attrs.value( QLatin1String("department") ).isEmpty() ) { - addr.setDepartment( asUtf8( attrs[ QLatin1String("department") ].first() ) ); - } - - if ( !workAddr.isEmpty() ) { - addr.insertAddress( workAddr ); - } - - // phone - if ( !attrs.value( QLatin1String("homePhone") ).isEmpty() ) { - KABC::PhoneNumber homeNr = asUtf8( attrs[ QLatin1String("homePhone") ].first() ); - homeNr.setType( KABC::PhoneNumber::Home ); - addr.insertPhoneNumber( homeNr ); - } - - if ( !attrs.value( QLatin1String("telephoneNumber") ).isEmpty() ) { - KABC::PhoneNumber workNr = asUtf8( attrs[ QLatin1String("telephoneNumber") ].first() ); - workNr.setType( KABC::PhoneNumber::Work ); - addr.insertPhoneNumber( workNr ); - } - - if ( !attrs.value( QLatin1String("facsimileTelephoneNumber") ).isEmpty() ) { - KABC::PhoneNumber faxNr = asUtf8( attrs[ QLatin1String("facsimileTelephoneNumber") ].first() ); - faxNr.setType( KABC::PhoneNumber::Fax ); - addr.insertPhoneNumber( faxNr ); - } - - if ( !attrs.value( QLatin1String("mobile") ).isEmpty() ) { - KABC::PhoneNumber cellNr = asUtf8( attrs[ QLatin1String("mobile") ].first() ); - cellNr.setType( KABC::PhoneNumber::Cell ); - addr.insertPhoneNumber( cellNr ); - } - - if ( !attrs.value( QLatin1String("pager") ).isEmpty() ) { - KABC::PhoneNumber pagerNr = asUtf8( attrs[ QLatin1String("pager") ].first() ); - pagerNr.setType( KABC::PhoneNumber::Pager ); - addr.insertPhoneNumber( pagerNr ); - } + // Address + KABC::Address workAddr( KABC::Address::Work ); - return addr; + if ( !attrs.value( QLatin1String("department") ).isEmpty() ) { + addr.setDepartment( asUtf8( attrs[ QLatin1String("department") ].first() ) ); + } + + if ( !workAddr.isEmpty() ) { + addr.insertAddress( workAddr ); + } + + // phone + if ( !attrs.value( QLatin1String("homePhone") ).isEmpty() ) { + KABC::PhoneNumber homeNr = asUtf8( attrs[ QLatin1String("homePhone") ].first() ); + homeNr.setType( KABC::PhoneNumber::Home ); + addr.insertPhoneNumber( homeNr ); + } + + if ( !attrs.value( QLatin1String("telephoneNumber") ).isEmpty() ) { + KABC::PhoneNumber workNr = asUtf8( attrs[ QLatin1String("telephoneNumber") ].first() ); + workNr.setType( KABC::PhoneNumber::Work ); + addr.insertPhoneNumber( workNr ); + } + + if ( !attrs.value( QLatin1String("facsimileTelephoneNumber") ).isEmpty() ) { + KABC::PhoneNumber faxNr = asUtf8( attrs[ QLatin1String("facsimileTelephoneNumber") ].first() ); + faxNr.setType( KABC::PhoneNumber::Fax ); + addr.insertPhoneNumber( faxNr ); + } + + if ( !attrs.value( QLatin1String("mobile") ).isEmpty() ) { + KABC::PhoneNumber cellNr = asUtf8( attrs[ QLatin1String("mobile") ].first() ); + cellNr.setType( KABC::PhoneNumber::Cell ); + addr.insertPhoneNumber( cellNr ); + } + + if ( !attrs.value( QLatin1String("pager") ).isEmpty() ) { + KABC::PhoneNumber pagerNr = asUtf8( attrs[ QLatin1String("pager") ].first() ); + pagerNr.setType( KABC::PhoneNumber::Pager ); + addr.insertPhoneNumber( pagerNr ); + } + + return addr; } class ContactListModel : public QAbstractTableModel { - public: +public: enum Role { - ServerRole = Qt::UserRole + 1 + ServerRole = Qt::UserRole + 1 }; ContactListModel( QObject *parent ) - : QAbstractTableModel( parent ) + : QAbstractTableModel( parent ) { } void addContact( const KLDAP::LdapAttrMap &contact, const QString &server ) { - mContactList.append( contact ); - mServerList.append( server ); - reset(); + mContactList.append( contact ); + mServerList.append( server ); + reset(); } QPair contact( const QModelIndex &index ) const { - if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) { - return qMakePair( KLDAP::LdapAttrMap(), QString() ); - } + if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) { + return qMakePair( KLDAP::LdapAttrMap(), QString() ); + } - return qMakePair( mContactList.at( index.row() ), mServerList.at( index.row() ) ); + return qMakePair( mContactList.at( index.row() ), mServerList.at( index.row() ) ); } QString email( const QModelIndex &index ) const { - if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) { - return QString(); - } + if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) { + return QString(); + } - return asUtf8( mContactList.at( index.row() ).value( QLatin1String("mail") ).first() ).trimmed(); + return asUtf8( mContactList.at( index.row() ).value( QLatin1String("mail") ).first() ).trimmed(); } QString fullName( const QModelIndex &index ) const { - if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) { - return QString(); - } + if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) { + return QString(); + } - return asUtf8( mContactList.at( index.row() ).value( QLatin1String("cn") ).first() ).trimmed(); + return asUtf8( mContactList.at( index.row() ).value( QLatin1String("cn") ).first() ).trimmed(); } void clear() { - mContactList.clear(); - mServerList.clear(); - reset(); + mContactList.clear(); + mServerList.clear(); + reset(); } virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const { - if ( !parent.isValid() ) { - return mContactList.count(); - } else { - return 0; - } + if ( !parent.isValid() ) { + return mContactList.count(); + } else { + return 0; + } } virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const { - if ( !parent.isValid() ) { - return 18; - } else { - return 0; - } + if ( !parent.isValid() ) { + return 18; + } else { + return 0; + } } virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const { - if ( orientation == Qt::Vertical || role != Qt::DisplayRole || section < 0 || section > 17 ) { - return QVariant(); - } + if ( orientation == Qt::Vertical || role != Qt::DisplayRole || section < 0 || section > 17 ) { + return QVariant(); + } - switch ( section ) { + switch ( section ) { case 0: - return i18n( "Full Name" ); - break; + return i18n( "Full Name" ); + break; case 1: - return i18nc( "@title:column Column containing email addresses", "Email" ); - break; + return i18nc( "@title:column Column containing email addresses", "Email" ); + break; case 2: - return i18n( "Home Number" ); - break; + return i18n( "Home Number" ); + break; case 3: - return i18n( "Work Number" ); - break; + return i18n( "Work Number" ); + break; case 4: - return i18n( "Mobile Number" ); - break; + return i18n( "Mobile Number" ); + break; case 5: - return i18n( "Fax Number" ); - break; + return i18n( "Fax Number" ); + break; case 6: - return i18n( "Company" ); - break; + return i18n( "Company" ); + break; case 7: - return i18n( "Organization" ); - break; + return i18n( "Organization" ); + break; case 8: - return i18n( "Street" ); - break; + return i18n( "Street" ); + break; case 9: - return i18nc( "@title:column Column containing the residential state of the address", - "State" ); - break; + return i18nc( "@title:column Column containing the residential state of the address", + "State" ); + break; case 10: - return i18n( "Country" ); - break; + return i18n( "Country" ); + break; case 11: - return i18n( "Zip Code" ); - break; + return i18n( "Zip Code" ); + break; case 12: - return i18n( "Postal Address" ); - break; + return i18n( "Postal Address" ); + break; case 13: - return i18n( "City" ); - break; + return i18n( "City" ); + break; case 14: - return i18n( "Department" ); - break; + return i18n( "Department" ); + break; case 15: - return i18n( "Description" ); - break; + return i18n( "Description" ); + break; case 16: - return i18n( "User ID" ); - break; + return i18n( "User ID" ); + break; case 17: - return i18nc( "@title:column Column containing title of the person", "Title" ); - break; + return i18nc( "@title:column Column containing title of the person", "Title" ); + break; default: - return QVariant(); - break; - }; + return QVariant(); + break; + }; - return QVariant(); + return QVariant(); } virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const { - if ( !index.isValid() ) { - return QVariant(); - } + if ( !index.isValid() ) { + return QVariant(); + } - if ( index.row() < 0 || index.row() >= mContactList.count() || - index.column() < 0 || index.column() > 17 ) { - return QVariant(); - } + if ( index.row() < 0 || index.row() >= mContactList.count() || + index.column() < 0 || index.column() > 17 ) { + return QVariant(); + } - if ( role == ServerRole ) { - return mServerList.at( index.row() ); - } + if ( role == ServerRole ) { + return mServerList.at( index.row() ); + } - if ( (role != Qt::DisplayRole) && (role != Qt::ToolTipRole) ) { - return QVariant(); - } + if ( (role != Qt::DisplayRole) && (role != Qt::ToolTipRole) ) { + return QVariant(); + } - const KLDAP::LdapAttrMap map = mContactList.at( index.row() ); + const KLDAP::LdapAttrMap map = mContactList.at( index.row() ); - switch ( index.column() ) { + switch ( index.column() ) { case 0: - return join( map.value( QLatin1String("cn") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("cn") ), QLatin1String(", ") ); + break; case 1: - return join( map.value( QLatin1String("mail") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("mail") ), QLatin1String(", ") ); + break; case 2: - return join( map.value( QLatin1String("homePhone") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("homePhone") ), QLatin1String(", ") ); + break; case 3: - return join( map.value( QLatin1String("telephoneNumber") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("telephoneNumber") ), QLatin1String(", ") ); + break; case 4: - return join( map.value( QLatin1String("mobile") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("mobile") ), QLatin1String(", ") ); + break; case 5: - return join( map.value( QLatin1String("facsimileTelephoneNumber") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("facsimileTelephoneNumber") ), QLatin1String(", ") ); + break; case 6: - return join( map.value( QLatin1String("Company") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("Company") ), QLatin1String(", ") ); + break; case 7: - return join( map.value( QLatin1String("o") ), QLatin1String(", " )); - break; + return join( map.value( QLatin1String("o") ), QLatin1String(", " )); + break; case 8: - return join( map.value( QLatin1String("street") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("street") ), QLatin1String(", ") ); + break; case 9: - return join( map.value( QLatin1String("st") ), QLatin1String(", " )); - break; + return join( map.value( QLatin1String("st") ), QLatin1String(", " )); + break; case 10: - return join( map.value( QLatin1String("co") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("co") ), QLatin1String(", ") ); + break; case 11: - return join( map.value( QLatin1String("postalCode") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("postalCode") ), QLatin1String(", ") ); + break; case 12: - return join( map.value( QLatin1String("postalAddress") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("postalAddress") ), QLatin1String(", ") ); + break; case 13: - return join( map.value( QLatin1String("l") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("l") ), QLatin1String(", ") ); + break; case 14: - return join( map.value( QLatin1String("department") ),QLatin1String( ", " )); - break; + return join( map.value( QLatin1String("department") ),QLatin1String( ", " )); + break; case 15: - return join( map.value( QLatin1String("description") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("description") ), QLatin1String(", ") ); + break; case 16: - return join( map.value( QLatin1String("uid") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("uid") ), QLatin1String(", ") ); + break; case 17: - return join( map.value( QLatin1String("title") ), QLatin1String(", ") ); - break; + return join( map.value( QLatin1String("title") ), QLatin1String(", ") ); + break; default: - return QVariant(); - break; - } + return QVariant(); + break; + } - return QVariant(); + return QVariant(); } - private: +private: QList mContactList; QStringList mServerList; }; class LdapSearchDialog::Private { - public: +public: Private( LdapSearchDialog *qq ) - : q( qq ), - mNumHosts( 0 ), - mIsConfigured( false ), - mModel( 0 ) + : q( qq ), + mNumHosts( 0 ), + mIsConfigured( false ), + mModel( 0 ) { } QList< QPair > selectedItems() { - QList< QPair > contacts; + QList< QPair > contacts; - const QModelIndexList selected = mResultView->selectionModel()->selectedRows(); - for ( int i = 0; i < selected.count(); ++i ) { - contacts.append( mModel->contact( sortproxy->mapToSource(selected.at( i )) ) ); - } + const QModelIndexList selected = mResultView->selectionModel()->selectedRows(); + for ( int i = 0; i < selected.count(); ++i ) { + contacts.append( mModel->contact( sortproxy->mapToSource(selected.at( i )) ) ); + } - return contacts; + return contacts; } @@ -517,141 +517,142 @@ }; LdapSearchDialog::LdapSearchDialog( QWidget *parent ) - : KDialog( parent ), d( new Private( this ) ) + : KDialog( parent ), d( new Private( this ) ) { - setCaption( i18n( "Import Contacts from LDAP" ) ); - setButtons( /*Help |*/ User1 | User2 | Cancel ); - setDefaultButton( User1 ); - setModal( false ); - showButtonSeparator( true ); - setButtonGuiItem( KDialog::Cancel, KStandardGuiItem::close() ); - QFrame *page = new QFrame( this ); - setMainWidget( page ); - QVBoxLayout *topLayout = new QVBoxLayout( page ); - topLayout->setSpacing( spacingHint() ); - topLayout->setMargin( marginHint() ); - - QGroupBox *groupBox = new QGroupBox( i18n( "Search for Addresses in Directory" ), - page ); - QGridLayout *boxLayout = new QGridLayout(); - groupBox->setLayout( boxLayout ); - boxLayout->setSpacing( spacingHint() ); - boxLayout->setColumnStretch( 1, 1 ); - - QLabel *label = new QLabel( i18n( "Search for:" ), groupBox ); - boxLayout->addWidget( label, 0, 0 ); - - d->mSearchEdit = new KLineEdit( groupBox ); - d->mSearchEdit->setClearButtonShown(true); - boxLayout->addWidget( d->mSearchEdit, 0, 1 ); - label->setBuddy( d->mSearchEdit ); - - label = new QLabel( i18nc( "In LDAP attribute", "in" ), groupBox ); - boxLayout->addWidget( label, 0, 2 ); - - d->mFilterCombo = new KComboBox( groupBox ); - d->mFilterCombo->addItem( i18nc( "@item:inlistbox Name of the contact", "Name" ) ); - d->mFilterCombo->addItem( i18nc( "@item:inlistbox email address of the contact", "Email" ) ); - d->mFilterCombo->addItem( i18nc( "@item:inlistbox", "Home Number" ) ); - d->mFilterCombo->addItem( i18nc( "@item:inlistbox", "Work Number" ) ); - boxLayout->addWidget( d->mFilterCombo, 0, 3 ); - d->startSearchGuiItem = KGuiItem( i18nc( "@action:button Start searching", "&Search" ), QLatin1String("edit-find") ); - d->stopSearchGuiItem = KStandardGuiItem::stop(); - - QSize buttonSize; - d->mSearchButton = new KPushButton( groupBox ); - d->mSearchButton->setGuiItem(d->startSearchGuiItem); + setCaption( i18n( "Import Contacts from LDAP" ) ); + setButtons( /*Help |*/ User1 | User2 | Cancel ); + setDefaultButton( User1 ); + setModal( false ); + showButtonSeparator( true ); + setButtonGuiItem( KDialog::Cancel, KStandardGuiItem::close() ); + QFrame *page = new QFrame( this ); + setMainWidget( page ); + QVBoxLayout *topLayout = new QVBoxLayout( page ); + topLayout->setSpacing( spacingHint() ); + topLayout->setMargin( marginHint() ); + + QGroupBox *groupBox = new QGroupBox( i18n( "Search for Addresses in Directory" ), + page ); + QGridLayout *boxLayout = new QGridLayout(); + groupBox->setLayout( boxLayout ); + boxLayout->setSpacing( spacingHint() ); + boxLayout->setColumnStretch( 1, 1 ); + + QLabel *label = new QLabel( i18n( "Search for:" ), groupBox ); + boxLayout->addWidget( label, 0, 0 ); + + d->mSearchEdit = new KLineEdit( groupBox ); + d->mSearchEdit->setClearButtonShown(true); + boxLayout->addWidget( d->mSearchEdit, 0, 1 ); + label->setBuddy( d->mSearchEdit ); + + label = new QLabel( i18nc( "In LDAP attribute", "in" ), groupBox ); + boxLayout->addWidget( label, 0, 2 ); + + d->mFilterCombo = new KComboBox( groupBox ); + d->mFilterCombo->addItem( i18nc( "@item:inlistbox Name of the contact", "Name" ) ); + d->mFilterCombo->addItem( i18nc( "@item:inlistbox email address of the contact", "Email" ) ); + d->mFilterCombo->addItem( i18nc( "@item:inlistbox", "Home Number" ) ); + d->mFilterCombo->addItem( i18nc( "@item:inlistbox", "Work Number" ) ); + boxLayout->addWidget( d->mFilterCombo, 0, 3 ); + d->startSearchGuiItem = KGuiItem( i18nc( "@action:button Start searching", "&Search" ), QLatin1String("edit-find") ); + d->stopSearchGuiItem = KStandardGuiItem::stop(); + + QSize buttonSize; + d->mSearchButton = new KPushButton( groupBox ); + d->mSearchButton->setGuiItem(d->startSearchGuiItem); - buttonSize = d->mSearchButton->sizeHint(); - if ( buttonSize.width() < d->mSearchButton->sizeHint().width() ) { buttonSize = d->mSearchButton->sizeHint(); - } - d->mSearchButton->setFixedWidth( buttonSize.width() ); + if ( buttonSize.width() < d->mSearchButton->sizeHint().width() ) { + buttonSize = d->mSearchButton->sizeHint(); + } + d->mSearchButton->setFixedWidth( buttonSize.width() ); - d->mSearchButton->setDefault( true ); - boxLayout->addWidget( d->mSearchButton, 0, 4 ); + d->mSearchButton->setDefault( true ); + boxLayout->addWidget( d->mSearchButton, 0, 4 ); - d->mRecursiveCheckbox = new QCheckBox( i18n( "Recursive search" ), groupBox ); - d->mRecursiveCheckbox->setChecked( true ); - boxLayout->addWidget( d->mRecursiveCheckbox, 1, 0, 1, 5 ); + d->mRecursiveCheckbox = new QCheckBox( i18n( "Recursive search" ), groupBox ); + d->mRecursiveCheckbox->setChecked( true ); + boxLayout->addWidget( d->mRecursiveCheckbox, 1, 0, 1, 5 ); - d->mSearchType = new KComboBox( groupBox ); - d->mSearchType->addItem( i18n( "Contains" ) ); - d->mSearchType->addItem( i18n( "Starts With" ) ); - boxLayout->addWidget( d->mSearchType, 1, 3, 1, 2 ); + d->mSearchType = new KComboBox( groupBox ); + d->mSearchType->addItem( i18n( "Contains" ) ); + d->mSearchType->addItem( i18n( "Starts With" ) ); + boxLayout->addWidget( d->mSearchType, 1, 3, 1, 2 ); - topLayout->addWidget( groupBox ); + topLayout->addWidget( groupBox ); - d->mResultView = new QTableView( page ); - d->mResultView->setSelectionMode( QTableView::MultiSelection ); - d->mResultView->setSelectionBehavior( QTableView::SelectRows ); - d->mModel = new ContactListModel( d->mResultView ); + d->mResultView = new QTableView( page ); + d->mResultView->setSelectionMode( QTableView::MultiSelection ); + d->mResultView->setSelectionBehavior( QTableView::SelectRows ); + d->mModel = new ContactListModel( d->mResultView ); - d->sortproxy = new QSortFilterProxyModel( this ); - d->sortproxy->setSourceModel( d->mModel ); + d->sortproxy = new QSortFilterProxyModel( this ); + d->sortproxy->setSourceModel( d->mModel ); - d->mResultView->setModel( d->sortproxy ); - d->mResultView->verticalHeader()->hide(); - d->mResultView->setSortingEnabled(true); - d->mResultView->horizontalHeader()->setSortIndicatorShown(true); - connect( d->mResultView, SIGNAL(clicked(QModelIndex)), - SLOT(slotSelectionChanged()) ); - topLayout->addWidget( d->mResultView ); + d->mResultView->setModel( d->sortproxy ); + d->mResultView->verticalHeader()->hide(); + d->mResultView->setSortingEnabled(true); + d->mResultView->horizontalHeader()->setSortIndicatorShown(true); + connect( d->mResultView, SIGNAL(clicked(QModelIndex)), + SLOT(slotSelectionChanged()) ); + topLayout->addWidget( d->mResultView ); - d->mResultView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(d->mResultView, SIGNAL(customContextMenuRequested(QPoint)), - this, SLOT(slotCustomContextMenuRequested(QPoint))); + d->mResultView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(d->mResultView, SIGNAL(customContextMenuRequested(QPoint)), + this, SLOT(slotCustomContextMenuRequested(QPoint))); - QHBoxLayout *buttonLayout = new QHBoxLayout; - buttonLayout->setMargin(0); - topLayout->addLayout(buttonLayout); + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->setMargin(0); + topLayout->addLayout(buttonLayout); - d->progressIndication = new KPIMUtils::ProgressIndicatorLabel(i18n("Searching...")); - buttonLayout->addWidget(d->progressIndication); + d->progressIndication = new KPIMUtils::ProgressIndicatorLabel(i18n("Searching...")); + buttonLayout->addWidget(d->progressIndication); - KDialogButtonBox *buttons = new KDialogButtonBox( page, Qt::Horizontal ); - buttons->addButton( i18n( "Select All" ), - QDialogButtonBox::ActionRole, this, SLOT(slotSelectAll()) ); - buttons->addButton( i18n( "Unselect All" ), - QDialogButtonBox::ActionRole, this, SLOT(slotUnselectAll()) ); + KDialogButtonBox *buttons = new KDialogButtonBox( page, Qt::Horizontal ); + buttons->addButton( i18n( "Select All" ), + QDialogButtonBox::ActionRole, this, SLOT(slotSelectAll()) ); + buttons->addButton( i18n( "Unselect All" ), + QDialogButtonBox::ActionRole, this, SLOT(slotUnselectAll()) ); - buttonLayout->addWidget( buttons ); + buttonLayout->addWidget( buttons ); - setButtonText( User1, i18n( "Add Selected" ) ); - setButtonText( User2, i18n( "Configure LDAP Servers..." ) ); + setButtonText( User1, i18n( "Add Selected" ) ); + setButtonText( User2, i18n( "Configure LDAP Servers..." ) ); - connect( d->mRecursiveCheckbox, SIGNAL(toggled(bool)), - this, SLOT(slotSetScope(bool)) ); - connect( d->mSearchButton, SIGNAL(clicked()), - this, SLOT(slotStartSearch()) ); + connect( d->mRecursiveCheckbox, SIGNAL(toggled(bool)), + this, SLOT(slotSetScope(bool)) ); + connect( d->mSearchButton, SIGNAL(clicked()), + this, SLOT(slotStartSearch()) ); - setTabOrder( d->mSearchEdit, d->mFilterCombo ); - setTabOrder( d->mFilterCombo, d->mSearchButton ); - d->mSearchEdit->setFocus(); + setTabOrder( d->mSearchEdit, d->mFilterCombo ); + setTabOrder( d->mFilterCombo, d->mSearchButton ); + d->mSearchEdit->setFocus(); - connect( this, SIGNAL(user1Clicked()), this, SLOT(slotUser1()) ); - connect( this, SIGNAL(user2Clicked()), this, SLOT(slotUser2()) ); - d->slotSelectionChanged(); - d->restoreSettings(); + connect( this, SIGNAL(user1Clicked()), this, SLOT(slotUser1()) ); + connect( this, SIGNAL(user2Clicked()), this, SLOT(slotUser2()) ); + connect( this, SIGNAL(cancelClicked()), this, SLOT(slotCancelClicked())); + d->slotSelectionChanged(); + d->restoreSettings(); } LdapSearchDialog::~LdapSearchDialog() { - d->saveSettings(); - delete d; + d->saveSettings(); + delete d; } void LdapSearchDialog::setSearchText( const QString &text ) { - d->mSearchEdit->setText( text ); + d->mSearchEdit->setText( text ); } KABC::Addressee::List LdapSearchDialog::selectedContacts() const { - return d->mSelectedContacts; + return d->mSelectedContacts; } void LdapSearchDialog::slotCustomContextMenuRequested(const QPoint &pos) @@ -670,240 +671,247 @@ void LdapSearchDialog::Private::slotSelectionChanged() { - q->enableButton( KDialog::User1, mResultView->selectionModel()->hasSelection() ); + q->enableButton( KDialog::User1, mResultView->selectionModel()->hasSelection() ); } void LdapSearchDialog::Private::restoreSettings() { - // Create one KLDAP::LdapClient per selected server and configure it. + // Create one KLDAP::LdapClient per selected server and configure it. + + // First clean the list to make sure it is empty at + // the beginning of the process + qDeleteAll( mLdapClientList ) ; + mLdapClientList.clear(); + + KConfig *config = KLDAP::LdapClientSearchConfig::config(); + + KConfigGroup searchGroup( config, "LDAPSearch" ); + mSearchType->setCurrentIndex( searchGroup.readEntry( "SearchType", 0 ) ); + + // then read the config file and register all selected + // server in the list + KConfigGroup group( config, "LDAP" ); + mNumHosts = group.readEntry( "NumSelectedHosts", 0 ); + if ( !mNumHosts ) { + mIsConfigured = false; + } else { + mIsConfigured = true; + KLDAP::LdapClientSearchConfig *clientSearchConfig = new KLDAP::LdapClientSearchConfig; + for ( int j = 0; j < mNumHosts; ++j ) { + KLDAP::LdapServer ldapServer; + KLDAP::LdapClient *ldapClient = new KLDAP::LdapClient( 0, q ); + clientSearchConfig->readConfig( ldapServer, group, j, true ); + ldapClient->setServer( ldapServer ); + QStringList attrs; + + QMap::ConstIterator end(adrbookattr2ldap().constEnd()); + for ( QMap::ConstIterator it = adrbookattr2ldap().constBegin(); + it != end; ++it ) { + attrs << *it; + } + + ldapClient->setAttributes( attrs ); + + q->connect( ldapClient, SIGNAL(result(KLDAP::LdapClient,KLDAP::LdapObject)), + q, SLOT(slotAddResult(KLDAP::LdapClient,KLDAP::LdapObject)) ); + q->connect( ldapClient, SIGNAL(done()), + q, SLOT(slotSearchDone()) ); + q->connect( ldapClient, SIGNAL(error(QString)), + q, SLOT(slotError(QString)) ); - // First clean the list to make sure it is empty at - // the beginning of the process - qDeleteAll( mLdapClientList ) ; - mLdapClientList.clear(); - - KConfig *config = KLDAP::LdapClientSearchConfig::config(); - - KConfigGroup searchGroup( config, "LDAPSearch" ); - mSearchType->setCurrentIndex( searchGroup.readEntry( "SearchType", 0 ) ); - - // then read the config file and register all selected - // server in the list - KConfigGroup group( config, "LDAP" ); - mNumHosts = group.readEntry( "NumSelectedHosts", 0 ); - if ( !mNumHosts ) { - mIsConfigured = false; - } else { - mIsConfigured = true; - KLDAP::LdapClientSearchConfig *clientSearchConfig = new KLDAP::LdapClientSearchConfig; - for ( int j = 0; j < mNumHosts; ++j ) { - KLDAP::LdapServer ldapServer; - KLDAP::LdapClient *ldapClient = new KLDAP::LdapClient( 0, q ); - clientSearchConfig->readConfig( ldapServer, group, j, true ); - ldapClient->setServer( ldapServer ); - QStringList attrs; - - QMap::ConstIterator end(adrbookattr2ldap().constEnd()); - for ( QMap::ConstIterator it = adrbookattr2ldap().constBegin(); - it != end; ++it ) { - attrs << *it; - } - - ldapClient->setAttributes( attrs ); - - q->connect( ldapClient, SIGNAL(result(KLDAP::LdapClient,KLDAP::LdapObject)), - q, SLOT(slotAddResult(KLDAP::LdapClient,KLDAP::LdapObject)) ); - q->connect( ldapClient, SIGNAL(done()), - q, SLOT(slotSearchDone()) ); - q->connect( ldapClient, SIGNAL(error(QString)), - q, SLOT(slotError(QString)) ); + mLdapClientList.append( ldapClient ); + } + delete clientSearchConfig; - mLdapClientList.append( ldapClient ); + mModel->clear(); } - delete clientSearchConfig; + KConfigGroup groupHeader( config, "Headers" ); + mResultView->horizontalHeader()->restoreState(groupHeader.readEntry("HeaderState",QByteArray())); - mModel->clear(); - } - KConfigGroup groupHeader( config, "Headers" ); - mResultView->horizontalHeader()->restoreState(groupHeader.readEntry("HeaderState",QByteArray())); - - KConfigGroup groupSize( config, "Size" ); - const QSize dialogSize = groupSize.readEntry( "Size", QSize() ); - if ( dialogSize.isValid() ) { - q->resize( dialogSize ); - } else { - q->resize( QSize( 600, 400 ).expandedTo( q->minimumSizeHint() ) ); - } + KConfigGroup groupSize( config, "Size" ); + const QSize dialogSize = groupSize.readEntry( "Size", QSize() ); + if ( dialogSize.isValid() ) { + q->resize( dialogSize ); + } else { + q->resize( QSize( 600, 400 ).expandedTo( q->minimumSizeHint() ) ); + } } void LdapSearchDialog::Private::saveSettings() { - KConfig *config = KLDAP::LdapClientSearchConfig::config(); - KConfigGroup group( config, "LDAPSearch" ); - group.writeEntry( "SearchType", mSearchType->currentIndex() ); - - KConfigGroup groupHeader( config, "Headers" ); - groupHeader.writeEntry( "HeaderState", mResultView->horizontalHeader()->saveState()); - groupHeader.sync(); - - KConfigGroup size( config, "Size" ); - size.writeEntry( "Size", q->size()); - size.sync(); + KConfig *config = KLDAP::LdapClientSearchConfig::config(); + KConfigGroup group( config, "LDAPSearch" ); + group.writeEntry( "SearchType", mSearchType->currentIndex() ); + + KConfigGroup groupHeader( config, "Headers" ); + groupHeader.writeEntry( "HeaderState", mResultView->horizontalHeader()->saveState()); + groupHeader.sync(); + + KConfigGroup size( config, "Size" ); + size.writeEntry( "Size", q->size()); + size.sync(); - group.sync(); + group.sync(); } void LdapSearchDialog::Private::cancelQuery() { - Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) { - client->cancelQuery(); - } + Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) { + client->cancelQuery(); + } } void LdapSearchDialog::Private::slotAddResult( const KLDAP::LdapClient &client, const KLDAP::LdapObject &obj ) { - mModel->addContact( obj.attributes(), client.server().host() ); + mModel->addContact( obj.attributes(), client.server().host() ); } void LdapSearchDialog::Private::slotSetScope( bool rec ) { Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) { - if ( rec ) { - client->setScope( QLatin1String("sub") ); - } else { - client->setScope( QLatin1String("one") ); + if ( rec ) { + client->setScope( QLatin1String("sub") ); + } else { + client->setScope( QLatin1String("one") ); + } } - } } void LdapSearchDialog::Private::slotStartSearch() { - cancelQuery(); + cancelQuery(); - if ( !mIsConfigured ) { - KMessageBox::error( q, i18n( "You must select an LDAP server before searching." ) ); - q->slotUser2(); - return; - } + if ( !mIsConfigured ) { + KMessageBox::error( q, i18n( "You must select an LDAP server before searching." ) ); + q->slotUser2(); + return; + } #ifndef QT_NO_CURSOR - QApplication::setOverrideCursor( Qt::WaitCursor ); + QApplication::setOverrideCursor( Qt::WaitCursor ); #endif - mSearchButton->setGuiItem(stopSearchGuiItem); - progressIndication->start(); + mSearchButton->setGuiItem(stopSearchGuiItem); + progressIndication->start(); + + q->disconnect( mSearchButton, SIGNAL(clicked()), + q, SLOT(slotStartSearch()) ); + q->connect( mSearchButton, SIGNAL(clicked()), + q, SLOT(slotStopSearch()) ); - q->disconnect( mSearchButton, SIGNAL(clicked()), - q, SLOT(slotStartSearch()) ); - q->connect( mSearchButton, SIGNAL(clicked()), - q, SLOT(slotStopSearch()) ); - - const bool startsWith = (mSearchType->currentIndex() == 1); - - const QString filter = makeFilter( mSearchEdit->text().trimmed(), - mFilterCombo->currentText(), startsWith ); - - // loop in the list and run the KLDAP::LdapClients - mModel->clear(); - Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) { - client->startQuery( filter ); - } + const bool startsWith = (mSearchType->currentIndex() == 1); + + const QString filter = makeFilter( mSearchEdit->text().trimmed(), + mFilterCombo->currentText(), startsWith ); + + // loop in the list and run the KLDAP::LdapClients + mModel->clear(); + Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) { + client->startQuery( filter ); + } - saveSettings(); + saveSettings(); } void LdapSearchDialog::Private::slotStopSearch() { - cancelQuery(); - slotSearchDone(); + cancelQuery(); + slotSearchDone(); } void LdapSearchDialog::Private::slotSearchDone() { - // If there are no more active clients, we are done. - Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) { - if ( client->isActive() ) { - return; - } - } - - q->disconnect( mSearchButton, SIGNAL(clicked()), - q, SLOT(slotStopSearch()) ); - q->connect( mSearchButton, SIGNAL(clicked()), - q, SLOT(slotStartSearch()) ); + // If there are no more active clients, we are done. + Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) { + if ( client->isActive() ) { + return; + } + } - mSearchButton->setGuiItem(startSearchGuiItem); - progressIndication->stop(); + q->disconnect( mSearchButton, SIGNAL(clicked()), + q, SLOT(slotStopSearch()) ); + q->connect( mSearchButton, SIGNAL(clicked()), + q, SLOT(slotStartSearch()) ); + + mSearchButton->setGuiItem(startSearchGuiItem); + progressIndication->stop(); #ifndef QT_NO_CURSOR - QApplication::restoreOverrideCursor(); + QApplication::restoreOverrideCursor(); #endif } void LdapSearchDialog::Private::slotError( const QString &error ) { #ifndef QT_NO_CURSOR - QApplication::restoreOverrideCursor(); + QApplication::restoreOverrideCursor(); #endif - KMessageBox::error( q, error ); + KMessageBox::error( q, error ); } void LdapSearchDialog::closeEvent( QCloseEvent *e ) { - d->slotStopSearch(); - e->accept(); + d->slotStopSearch(); + e->accept(); } void LdapSearchDialog::Private::slotUnselectAll() { - mResultView->clearSelection(); - slotSelectionChanged(); + mResultView->clearSelection(); + slotSelectionChanged(); } void LdapSearchDialog::Private::slotSelectAll() { - mResultView->selectAll(); - slotSelectionChanged(); + mResultView->selectAll(); + slotSelectionChanged(); } void LdapSearchDialog::slotUser1() { - // Import selected items + // Import selected items - d->mSelectedContacts.clear(); + d->mSelectedContacts.clear(); - const QList< QPair >& items = d->selectedItems(); + const QList< QPair >& items = d->selectedItems(); - if ( !items.isEmpty() ) { - const QDateTime now = QDateTime::currentDateTime(); + if ( !items.isEmpty() ) { + const QDateTime now = QDateTime::currentDateTime(); - for ( int i = 0; i < items.count(); ++i ) { - KABC::Addressee contact = convertLdapAttributesToAddressee( items.at( i ).first ); + for ( int i = 0; i < items.count(); ++i ) { + KABC::Addressee contact = convertLdapAttributesToAddressee( items.at( i ).first ); - // set a comment where the contact came from - contact.setNote( i18nc( "arguments are host name, datetime", - "Imported from LDAP directory %1 on %2", - items.at( i ).second, KGlobal::locale()->formatDateTime( now ) ) ); + // set a comment where the contact came from + contact.setNote( i18nc( "arguments are host name, datetime", + "Imported from LDAP directory %1 on %2", + items.at( i ).second, KGlobal::locale()->formatDateTime( now ) ) ); - d->mSelectedContacts.append( contact ); + d->mSelectedContacts.append( contact ); + } } - } - emit contactsAdded(); + d->slotStopSearch(); + emit contactsAdded(); - accept(); + accept(); } void LdapSearchDialog::slotUser2() { - // Configure LDAP servers + // Configure LDAP servers - KCMultiDialog dialog( this ); - dialog.setCaption( i18n( "Configure the Address Book LDAP Settings" ) ); - dialog.addModule( QLatin1String("kcmldap.desktop") ); + KCMultiDialog dialog( this ); + dialog.setCaption( i18n( "Configure the Address Book LDAP Settings" ) ); + dialog.addModule( QLatin1String("kcmldap.desktop") ); - if ( dialog.exec() ) { //krazy:exclude=crashy - d->restoreSettings(); - } + if ( dialog.exec() ) { //krazy:exclude=crashy + d->restoreSettings(); + } +} + +void LdapSearchDialog::slotCancelClicked() +{ + d->slotStopSearch(); + reject(); } #include "moc_ldapsearchdialog.cpp" diff -Nru kdepim-4.12.97/libkdepim/ldap/ldapsearchdialog.h kdepim-4.13.0/libkdepim/ldap/ldapsearchdialog.h --- kdepim-4.12.97/libkdepim/ldap/ldapsearchdialog.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/ldap/ldapsearchdialog.h 2014-04-10 07:40:20.000000000 +0000 @@ -47,9 +47,9 @@ */ class KDEPIM_EXPORT LdapSearchDialog : public KDialog { - Q_OBJECT + Q_OBJECT - public: +public: /** * Creates a new ldap search dialog. * @@ -73,22 +73,23 @@ */ KABC::Addressee::List selectedContacts() const; - Q_SIGNALS: +Q_SIGNALS: /** * This signal is emitted whenever the user clicked the * 'Add Selected' button. */ void contactsAdded(); - protected Q_SLOTS: +protected Q_SLOTS: void slotUser1(); void slotUser2(); void slotCustomContextMenuRequested(const QPoint&); + void slotCancelClicked(); - protected: +protected: void closeEvent( QCloseEvent* ); - private: +private: //@cond PRIVATE class Private; Private* const d; diff -Nru kdepim-4.12.97/libkdepim/misc/broadcaststatus.cpp kdepim-4.13.0/libkdepim/misc/broadcaststatus.cpp --- kdepim-4.12.97/libkdepim/misc/broadcaststatus.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/misc/broadcaststatus.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -35,44 +35,44 @@ static void deleteGlobalStaticBroadcastStatus() { - delete instance_; - instance_ = 0; + delete instance_; + instance_ = 0; } namespace KPIM { BroadcastStatus *BroadcastStatus::instance() { - if ( !instance_ ) { - instance_ = new BroadcastStatus(); - qAddPostRoutine( deleteGlobalStaticBroadcastStatus ); - } - return instance_; + if ( !instance_ ) { + instance_ = new BroadcastStatus(); + qAddPostRoutine( deleteGlobalStaticBroadcastStatus ); + } + return instance_; } BroadcastStatus::BroadcastStatus() - :mTransientActive( false ) + :mTransientActive( false ) { } BroadcastStatus::~BroadcastStatus() { - instance_ = 0; + instance_ = 0; } void BroadcastStatus::setStatusMsg( const QString &message ) { - mStatusMsg = message; - if( !mTransientActive ) { - emit statusMsg( message ); - } + mStatusMsg = message; + if( !mTransientActive ) { + emit statusMsg( message ); + } } void BroadcastStatus::setStatusMsgWithTimestamp( const QString &message ) { - KLocale *locale = KGlobal::locale(); - setStatusMsg( i18nc( "%1 is a time, %2 is a status message", "[%1] %2", - locale->formatTime( QTime::currentTime(), true ), message ) ); + KLocale *locale = KGlobal::locale(); + setStatusMsg( i18nc( "%1 is a time, %2 is a status message", "[%1] %2", + locale->formatTime( QTime::currentTime(), true ), message ) ); } void BroadcastStatus::setStatusMsgTransmissionCompleted( int numMessages, @@ -82,37 +82,37 @@ bool mLeaveOnServer, KPIM::ProgressItem *item ) { - QString statusMsg; - if ( numMessages > 0 ) { - if ( numBytes != -1 ) { - if ( ( numBytesToRead != numBytes ) && mLeaveOnServer ) { - statusMsg = i18np( "Transmission complete. %1 new message (%2 KB). " - "%3 KB remaining on the server.", - "Transmission complete. %1 new messages (%2 KB). " - "%3 KB remaining on the server.", - numMessages, - numBytesRead / 1024, - numBytes / 1024 ); - } else { - statusMsg = i18np( "Transmission complete. %1 message (%2 KB).", - "Transmission complete. %1 messages (%2 KB).", - numMessages, - numBytesRead / 1024 ); - } + QString statusMsg; + if ( numMessages > 0 ) { + if ( numBytes != -1 ) { + if ( ( numBytesToRead != numBytes ) && mLeaveOnServer ) { + statusMsg = i18np( "Transmission complete. %1 new message (%2 KB). " + "%3 KB remaining on the server.", + "Transmission complete. %1 new messages (%2 KB). " + "%3 KB remaining on the server.", + numMessages, + numBytesRead / 1024, + numBytes / 1024 ); + } else { + statusMsg = i18np( "Transmission complete. %1 message (%2 KB).", + "Transmission complete. %1 messages (%2 KB).", + numMessages, + numBytesRead / 1024 ); + } + } else { + statusMsg = i18np( "Transmission complete. %1 new message.", + "Transmission complete. %1 new messages.", + numMessages ); + } } else { - statusMsg = i18np( "Transmission complete. %1 new message.", - "Transmission complete. %1 new messages.", - numMessages ); - } - } else { - statusMsg = i18n( "Transmission complete. No new messages." ); - } - - setStatusMsgWithTimestamp( statusMsg ); - - if ( item ) { - item->setStatus( statusMsg ); - } + statusMsg = i18n( "Transmission complete. No new messages." ); + } + + setStatusMsgWithTimestamp( statusMsg ); + + if ( item ) { + item->setStatus( statusMsg ); + } } void BroadcastStatus::setStatusMsgTransmissionCompleted( const QString &account, @@ -123,59 +123,59 @@ bool mLeaveOnServer, KPIM::ProgressItem *item ) { - QString statusMsg; - if ( numMessages > 0 ) { - if ( numBytes != -1 ) { - if ( ( numBytesToRead != numBytes ) && mLeaveOnServer ) { - statusMsg = i18np( "Transmission for account %4 complete. " - "%1 new message (%2 KB). " - "%3 KB remaining on the server.", - "Transmission for account %4 complete. " - "%1 new messages (%2 KB). " - "%3 KB remaining on the server.", - numMessages, - numBytesRead / 1024, - numBytes / 1024, - account ); - } else { - statusMsg = i18np( "Transmission for account %3 complete. " - "%1 message (%2 KB).", - "Transmission for account %3 complete. " - "%1 messages (%2 KB).", - numMessages, - numBytesRead / 1024, - account ); - } + QString statusMsg; + if ( numMessages > 0 ) { + if ( numBytes != -1 ) { + if ( ( numBytesToRead != numBytes ) && mLeaveOnServer ) { + statusMsg = i18np( "Transmission for account %4 complete. " + "%1 new message (%2 KB). " + "%3 KB remaining on the server.", + "Transmission for account %4 complete. " + "%1 new messages (%2 KB). " + "%3 KB remaining on the server.", + numMessages, + numBytesRead / 1024, + numBytes / 1024, + account ); + } else { + statusMsg = i18np( "Transmission for account %3 complete. " + "%1 message (%2 KB).", + "Transmission for account %3 complete. " + "%1 messages (%2 KB).", + numMessages, + numBytesRead / 1024, + account ); + } + } else { + statusMsg = i18np( "Transmission for account %2 complete. " + "%1 new message.", + "Transmission for account %2 complete. " + "%1 new messages.", + numMessages, + account ); + } } else { - statusMsg = i18np( "Transmission for account %2 complete. " - "%1 new message.", - "Transmission for account %2 complete. " - "%1 new messages.", - numMessages, - account ); - } - } else { - statusMsg = i18n( "Transmission for account %1 complete. No new messages.", account ); - } - - setStatusMsgWithTimestamp( statusMsg ); - - if ( item ) { - item->setStatus( statusMsg ); - } + statusMsg = i18n( "Transmission for account %1 complete. No new messages.", account ); + } + + setStatusMsgWithTimestamp( statusMsg ); + + if ( item ) { + item->setStatus( statusMsg ); + } } void BroadcastStatus::setTransientStatusMsg( const QString &msg ) { - mTransientActive = true; - emit statusMsg( msg ); + mTransientActive = true; + emit statusMsg( msg ); } void BroadcastStatus::reset() { - mTransientActive = false; - // restore - emit statusMsg( mStatusMsg ); + mTransientActive = false; + // restore + emit statusMsg( mStatusMsg ); } } diff -Nru kdepim-4.12.97/libkdepim/misc/broadcaststatus.h kdepim-4.13.0/libkdepim/misc/broadcaststatus.h --- kdepim-4.12.97/libkdepim/misc/broadcaststatus.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/misc/broadcaststatus.h 2014-04-10 07:40:20.000000000 +0000 @@ -40,9 +40,9 @@ class KDEPIM_EXPORT BroadcastStatus : public QObject { - Q_OBJECT + Q_OBJECT - public: +public: virtual ~BroadcastStatus(); /** Return the instance of the singleton object for this class */ @@ -69,7 +69,7 @@ bool mLeaveOnServer = false, KPIM::ProgressItem *progressItem = 0 ); - public Q_SLOTS: +public Q_SLOTS: /** Emit an update status bar signal. It's a slot so it can be hooked up to other signals. @@ -88,11 +88,11 @@ */ void reset(); - Q_SIGNALS: +Q_SIGNALS: /** Emitted when setStatusMsg is called. */ void statusMsg( const QString & ); - protected: +protected: BroadcastStatus(); QString mStatusMsg; bool mTransientActive; diff -Nru kdepim-4.12.97/libkdepim/misc/maillistdrag.cpp kdepim-4.13.0/libkdepim/misc/maillistdrag.cpp --- kdepim-4.12.97/libkdepim/misc/maillistdrag.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/misc/maillistdrag.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -39,54 +39,54 @@ // Have to define before use QDataStream& operator<< ( QDataStream &s, const MailSummary &d ) { - s << d.serialNumber(); - s << d.messageId(); - s << d.subject(); - s << d.from(); - s << d.to(); - KDateTime tempTime; - tempTime.setTime_t( d.date() ); - s << tempTime.dateTime(); - return s; + s << d.serialNumber(); + s << d.messageId(); + s << d.subject(); + s << d.from(); + s << d.to(); + KDateTime tempTime; + tempTime.setTime_t( d.date() ); + s << tempTime.dateTime(); + return s; } QDataStream& operator>> ( QDataStream &s, MailSummary &d ) { - quint32 serialNumber; - QString messageId, subject, from, to; - time_t date; - s >> serialNumber; - s >> messageId; - s >> subject; - s >> from; - s >> to; - QDateTime tempTime; - s >> tempTime; - date = KDateTime( tempTime ).toTime_t(); - d.set( serialNumber, messageId, subject, from, to, date ); - return s; + quint32 serialNumber; + QString messageId, subject, from, to; + time_t date; + s >> serialNumber; + s >> messageId; + s >> subject; + s >> from; + s >> to; + QDateTime tempTime; + s >> tempTime; + date = KDateTime( tempTime ).toTime_t(); + d.set( serialNumber, messageId, subject, from, to, date ); + return s; } QDataStream& operator<< ( QDataStream &s, const MailList &mailList ) { - MailList::const_iterator it; - MailList::const_iterator end( mailList.constEnd() ); - for (it = mailList.constBegin(); it!=end; ++it) { - MailSummary mailDrag = *it; - s << mailDrag; - } - return s; + MailList::const_iterator it; + MailList::const_iterator end( mailList.constEnd() ); + for (it = mailList.constBegin(); it!=end; ++it) { + MailSummary mailDrag = *it; + s << mailDrag; + } + return s; } QDataStream& operator>> ( QDataStream &s, MailList &mailList ) { - mailList.clear(); - MailSummary mailDrag; - while (!s.atEnd()) { - s >> mailDrag; - mailList.append( mailDrag ); - } - return s; + mailList.clear(); + MailSummary mailDrag; + while (!s.atEnd()) { + s >> mailDrag; + mailList.append( mailDrag ); + } + return s; } MailSummary::MailSummary( quint32 serialNumber, const QString &messageId, @@ -143,134 +143,134 @@ QString MailList::mimeDataType() { - return QLatin1String( "x-kmail-drag/message-list" ); + return QLatin1String( "x-kmail-drag/message-list" ); } bool MailList::canDecode( const QMimeData *md ) { - return md->hasFormat( mimeDataType() ); + return md->hasFormat( mimeDataType() ); } void MailList::populateMimeData( QMimeData *md ) { - /* We have three different possible mime types: x-kmail-drag/message-list, message/rfc822, and URL + /* We have three different possible mime types: x-kmail-drag/message-list, message/rfc822, and URL Add them in this order */ - /* Popuplate the MimeData with the custom streaming x-kmail-drag/message-list mime type */ - if ( count() ) { - QByteArray array; - QBuffer buffer( &array, 0 ); - buffer.open( QIODevice::WriteOnly); - QDataStream stream( &buffer ); - stream << (*this); - buffer.close(); - md->setData( MailList::mimeDataType(), array ); - } + /* Popuplate the MimeData with the custom streaming x-kmail-drag/message-list mime type */ + if ( count() ) { + QByteArray array; + QBuffer buffer( &array, 0 ); + buffer.open( QIODevice::WriteOnly); + QDataStream stream( &buffer ); + stream << (*this); + buffer.close(); + md->setData( MailList::mimeDataType(), array ); + } } MailList MailList::fromMimeData( const QMimeData *md ) { - if ( canDecode(md) ) { - return decode( md->data( mimeDataType() ) ); - } else { - return MailList(); - } + if ( canDecode(md) ) { + return decode( md->data( mimeDataType() ) ); + } else { + return MailList(); + } } MailList MailList::decode( const QByteArray& payload ) { - MailList mailList; - // A read-only data stream - QDataStream stream( payload ); - if ( payload.size() ) { - stream >> mailList; - } - return mailList; + MailList mailList; + // A read-only data stream + QDataStream stream( payload ); + if ( payload.size() ) { + stream >> mailList; + } + return mailList; } QByteArray MailList::serialsFromMimeData( const QMimeData *md ) { - MailList mailList = fromMimeData( md ); - if ( mailList.count() ) { - MailList::const_iterator it; - QByteArray a; - QBuffer buffer( &a ); - buffer.open( QIODevice::WriteOnly ); - QDataStream stream( &buffer ); - MailList::const_iterator end( mailList.constEnd() ); - for (it = mailList.constBegin(); it != end; ++it) { - MailSummary mailDrag = *it; - stream << mailDrag.serialNumber(); - } - buffer.close(); - return a; - } else { - return QByteArray(); - } + MailList mailList = fromMimeData( md ); + if ( mailList.count() ) { + MailList::const_iterator it; + QByteArray a; + QBuffer buffer( &a ); + buffer.open( QIODevice::WriteOnly ); + QDataStream stream( &buffer ); + MailList::const_iterator end( mailList.constEnd() ); + for (it = mailList.constBegin(); it != end; ++it) { + MailSummary mailDrag = *it; + stream << mailDrag.serialNumber(); + } + buffer.close(); + return a; + } else { + return QByteArray(); + } } MailListMimeData::MailListMimeData( MailTextSource *src ) - : mMailTextSource( src ) + : mMailTextSource( src ) { } MailListMimeData::~MailListMimeData() { - delete mMailTextSource; - mMailTextSource = 0; + delete mMailTextSource; + mMailTextSource = 0; } bool MailListMimeData::hasFormat ( const QString & mimeType ) const { - if ( mimeType == QLatin1String( "message/rfc822" ) && mMailTextSource ) - return true; - else - return QMimeData::hasFormat( mimeType ); + if ( mimeType == QLatin1String( "message/rfc822" ) && mMailTextSource ) + return true; + else + return QMimeData::hasFormat( mimeType ); } QStringList MailListMimeData::formats () const { - QStringList theFormats = QMimeData::formats(); - if ( mMailTextSource ) - theFormats.prepend( QLatin1String( "message/rfc822" ) ); - return theFormats; + QStringList theFormats = QMimeData::formats(); + if ( mMailTextSource ) + theFormats.prepend( QLatin1String( "message/rfc822" ) ); + return theFormats; } QVariant MailListMimeData::retrieveData( const QString & mimeType, QVariant::Type type ) const { - if ( ( mimeType == QLatin1String( "message/rfc822" ) ) && mMailTextSource ) { + if ( ( mimeType == QLatin1String( "message/rfc822" ) ) && mMailTextSource ) { - if ( mMails.isEmpty() ) { - MailList list = MailList::fromMimeData( this ); - KProgressDialog *dlg = new KProgressDialog( 0, QString(), - i18n("Retrieving and storing messages...") ); - dlg->setWindowModality( Qt::WindowModal ); - dlg->setAllowCancel( true ); - dlg->progressBar()->setMaximum( list.size() ); - int i = 0; - dlg->progressBar()->setValue( i ); - dlg->show(); - MailList::ConstIterator end( list.constEnd() ); - for ( MailList::ConstIterator it = list.constBegin(); it != end; ++it ) { - - // Get the serial number from the mail summary and use the mail text source - // to get the actual text of the mail. - MailSummary mailSummary = *it; - mMails.append( mMailTextSource->text( mailSummary.serialNumber() ) ); - if ( dlg->wasCancelled() ) { - break; - } - dlg->progressBar()->setValue(++i); + if ( mMails.isEmpty() ) { + MailList list = MailList::fromMimeData( this ); + KProgressDialog *dlg = new KProgressDialog( 0, QString(), + i18n("Retrieving and storing messages...") ); + dlg->setWindowModality( Qt::WindowModal ); + dlg->setAllowCancel( true ); + dlg->progressBar()->setMaximum( list.size() ); + int i = 0; + dlg->progressBar()->setValue( i ); + dlg->show(); + MailList::ConstIterator end( list.constEnd() ); + for ( MailList::ConstIterator it = list.constBegin(); it != end; ++it ) { + + // Get the serial number from the mail summary and use the mail text source + // to get the actual text of the mail. + MailSummary mailSummary = *it; + mMails.append( mMailTextSource->text( mailSummary.serialNumber() ) ); + if ( dlg->wasCancelled() ) { + break; + } + dlg->progressBar()->setValue(++i); #ifdef __GNUC__ #warning Port me! #endif - //kapp->eventLoop()->processEvents(QEventLoop::ExcludeSocketNotifiers); - } - delete dlg; - } - return mMails; - } - else - return QMimeData::retrieveData( mimeType, type ); + //kapp->eventLoop()->processEvents(QEventLoop::ExcludeSocketNotifiers); + } + delete dlg; + } + return mMails; + } + else + return QMimeData::retrieveData( mimeType, type ); } diff -Nru kdepim-4.12.97/libkdepim/misc/maillistdrag.h kdepim-4.13.0/libkdepim/misc/maillistdrag.h --- kdepim-4.12.97/libkdepim/misc/maillistdrag.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/misc/maillistdrag.h 2014-04-10 07:40:20.000000000 +0000 @@ -91,8 +91,8 @@ #endif KDE_DUMMY_COMPARISON_OPERATOR(MailSummary) -private: - quint32 mSerialNumber; + private: + quint32 mSerialNumber; QString mMessageId, mSubject, mFrom, mTo; time_t mDate; }; @@ -104,7 +104,7 @@ Object for the drag object to call-back for message fulltext. */ class KDEPIM_EXPORT MailTextSource { -public: + public: MailTextSource() {} virtual ~MailTextSource() {} @@ -116,7 +116,7 @@ */ class KDEPIM_EXPORT MailList : public QList { - public: +public: static QString mimeDataType(); static bool canDecode( const QMimeData*md ); static MailList fromMimeData( const QMimeData*md ); @@ -141,7 +141,7 @@ */ class KDEPIM_EXPORT MailListMimeData : public QMimeData { - public: +public: /** * @param src The callback class for getting the full text of the mail. @@ -153,7 +153,7 @@ ~MailListMimeData(); - protected: +protected: /** * Reimplemented so that the message/rfc822 mimetype data can be retrieved @@ -166,7 +166,7 @@ virtual QStringList formats () const; - private: +private: MailTextSource *mMailTextSource; diff -Nru kdepim-4.12.97/libkdepim/misc/statisticsproxymodel.cpp kdepim-4.13.0/libkdepim/misc/statisticsproxymodel.cpp --- kdepim-4.12.97/libkdepim/misc/statisticsproxymodel.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/misc/statisticsproxymodel.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -44,149 +44,149 @@ */ class StatisticsProxyModel::Private { - public: +public: Private( StatisticsProxyModel *parent ) - : mParent( parent ), mToolTipEnabled( false ), mExtraColumnsEnabled( true ) + : mParent( parent ), mToolTipEnabled( false ), mExtraColumnsEnabled( true ) { } void getCountRecursive( const QModelIndex &index, qint64 &totalSize ) const { - Collection collection = qvariant_cast( index.data( EntityTreeModel::CollectionRole ) ); - // Do not assert on invalid collections, since a collection may be deleted - // in the meantime and deleted collections are invalid. - if ( collection.isValid() ) { - CollectionStatistics statistics = collection.statistics(); - totalSize += qMax( 0LL, statistics.size() ); - if ( index.model()->hasChildren( index ) ) { - const int rowCount = index.model()->rowCount( index ); - for ( int row = 0; row < rowCount; row++ ) { - static const int column = 0; - getCountRecursive( index.model()->index( row, column, index ), totalSize ); - } + Collection collection = qvariant_cast( index.data( EntityTreeModel::CollectionRole ) ); + // Do not assert on invalid collections, since a collection may be deleted + // in the meantime and deleted collections are invalid. + if ( collection.isValid() ) { + CollectionStatistics statistics = collection.statistics(); + totalSize += qMax( 0LL, statistics.size() ); + if ( index.model()->hasChildren( index ) ) { + const int rowCount = index.model()->rowCount( index ); + for ( int row = 0; row < rowCount; row++ ) { + static const int column = 0; + getCountRecursive( index.model()->index( row, column, index ), totalSize ); + } + } } - } } int sourceColumnCount() const { - return mParent->sourceModel()->columnCount(); + return mParent->sourceModel()->columnCount(); } QModelIndex sourceIndexAtFirstColumn(const QModelIndex& proxyIndex) const; QString toolTipForCollection( const QModelIndex &index, const Collection &collection ) { - QString bckColor = QApplication::palette().color( QPalette::ToolTipBase ).name(); - QString txtColor = QApplication::palette().color( QPalette::ToolTipText ).name(); + QString bckColor = QApplication::palette().color( QPalette::ToolTipBase ).name(); + QString txtColor = QApplication::palette().color( QPalette::ToolTipText ).name(); - QString tip = QString::fromLatin1( - "\n" - ); - const QString textDirection = ( QApplication::layoutDirection() == Qt::LeftToRight ) ? QLatin1String( "left" ) : QLatin1String( "right" ); - tip += QString::fromLatin1( - " \n" - " \n" - " \n" - ).arg( txtColor ).arg( bckColor ).arg( index.data( Qt::DisplayRole ).toString() ).arg( textDirection ); - - - tip += QString::fromLatin1( - " \n" - " \n" + ).arg( iconPath ).arg( icon_size_found ) ; + + if ( QApplication::layoutDirection() == Qt::LeftToRight ) + { + tip += tipInfo + QString::fromLatin1( "" \ + "
\n" - "
\n" - " %3\n" - "
\n" - "
\n" - ).arg( textDirection ); - - QString tipInfo; - tipInfo += QString::fromLatin1( - " %1: %2
\n" - " %3: %4

\n" - ).arg( i18n( "Total Messages" ) ).arg( collection.statistics().count() ) - .arg( i18n( "Unread Messages" ) ).arg( collection.statistics().unreadCount() ); - - if ( collection.hasAttribute() ) { - CollectionQuotaAttribute *quota = collection.attribute(); - if ( quota->currentValue() > -1 && quota->maximumValue() > 0 ) { - qreal percentage = ( 100.0 * quota->currentValue() ) / quota->maximumValue(); + QString tip = QString::fromLatin1( + "\n" + ); + const QString textDirection = ( QApplication::layoutDirection() == Qt::LeftToRight ) ? QLatin1String( "left" ) : QLatin1String( "right" ); + tip += QString::fromLatin1( + " \n" + " \n" + " \n" + ).arg( txtColor ).arg( bckColor ).arg( index.data( Qt::DisplayRole ).toString() ).arg( textDirection ); + + + tip += QString::fromLatin1( + " \n" + " \n" - ).arg( iconPath ).arg( icon_size_found ) ; - - if ( QApplication::layoutDirection() == Qt::LeftToRight ) - { - tip += tipInfo + QString::fromLatin1( "" \ - "
\n" + "
\n" + " %3\n" + "
\n" + "
\n" + ).arg( textDirection ); - if ( qAbs( percentage ) >= 0.01 ) { - QString percentStr = QString::number( percentage, 'f', 2 ); - tipInfo += QString::fromLatin1( - " %1: %2%
\n" - ).arg( i18n( "Quota" ) ).arg( percentStr ); - } - } - } - - qint64 currentFolderSize( collection.statistics().size() ); - tipInfo += QString::fromLatin1( - " %1: %2
\n" - ).arg( i18n( "Storage Size" ) ).arg( KIO::convertSize( (KIO::filesize_t)( currentFolderSize ) ) ); - - - qint64 totalSize = 0; - getCountRecursive( index, totalSize ); - totalSize -= currentFolderSize; - if (totalSize > 0 ) { + QString tipInfo; + tipInfo += QString::fromLatin1( + " %1: %2
\n" + " %3: %4

\n" + ).arg( i18n( "Total Messages" ) ).arg( collection.statistics().count() ) + .arg( i18n( "Unread Messages" ) ).arg( collection.statistics().unreadCount() ); + + if ( collection.hasAttribute() ) { + CollectionQuotaAttribute *quota = collection.attribute(); + if ( quota->currentValue() > -1 && quota->maximumValue() > 0 ) { + qreal percentage = ( 100.0 * quota->currentValue() ) / quota->maximumValue(); + + if ( qAbs( percentage ) >= 0.01 ) { + QString percentStr = QString::number( percentage, 'f', 2 ); + tipInfo += QString::fromLatin1( + " %1: %2%
\n" + ).arg( i18n( "Quota" ) ).arg( percentStr ); + } + } + } + + qint64 currentFolderSize( collection.statistics().size() ); tipInfo += QString::fromLatin1( - "%1: %2
" - ).arg( i18n("Subfolder Storage Size") ).arg( KIO::convertSize( (KIO::filesize_t)( totalSize ) ) ); - } - - QString iconName = CollectionUtils::defaultIconName( collection ); - if ( collection.hasAttribute() && - !collection.attribute()->iconName().isEmpty() ) { - if ( !collection.attribute()->activeIconName().isEmpty() && collection.statistics().unreadCount()> 0) { - iconName = collection.attribute()->activeIconName(); - } - else - iconName = collection.attribute()->iconName(); - } - - - int iconSizes[] = { 32, 22 }; - int icon_size_found = 32; - - QString iconPath; - - for ( int i = 0; i < 2; ++i ) { - iconPath = KIconLoader::global()->iconPath( iconName, -iconSizes[ i ], true ); - if ( !iconPath.isEmpty() ) { - icon_size_found = iconSizes[ i ]; - break; - } - } - - if ( iconPath.isEmpty() ) { - iconPath = KIconLoader::global()->iconPath( QLatin1String( "folder" ), -32, false ); - } - - QString tipIcon = QString::fromLatin1( - "
\n" - " \n" - "
\n" - "
" ).arg( textDirection ) + tipIcon; - } - else - { - tip += tipIcon + QString::fromLatin1( "" ).arg( textDirection ) + tipInfo; - } - - - tip += QString::fromLatin1( - "
" - ); + " %1: %2
\n" + ).arg( i18n( "Storage Size" ) ).arg( KIO::convertSize( (KIO::filesize_t)( currentFolderSize ) ) ); + + + qint64 totalSize = 0; + getCountRecursive( index, totalSize ); + totalSize -= currentFolderSize; + if (totalSize > 0 ) { + tipInfo += QString::fromLatin1( + "%1: %2
" + ).arg( i18n("Subfolder Storage Size") ).arg( KIO::convertSize( (KIO::filesize_t)( totalSize ) ) ); + } + + QString iconName = CollectionUtils::defaultIconName( collection ); + if ( collection.hasAttribute() && + !collection.attribute()->iconName().isEmpty() ) { + if ( !collection.attribute()->activeIconName().isEmpty() && collection.statistics().unreadCount()> 0) { + iconName = collection.attribute()->activeIconName(); + } + else + iconName = collection.attribute()->iconName(); + } + + + int iconSizes[] = { 32, 22 }; + int icon_size_found = 32; + + QString iconPath; - return tip; + for ( int i = 0; i < 2; ++i ) { + iconPath = KIconLoader::global()->iconPath( iconName, -iconSizes[ i ], true ); + if ( !iconPath.isEmpty() ) { + icon_size_found = iconSizes[ i ]; + break; + } + } + + if ( iconPath.isEmpty() ) { + iconPath = KIconLoader::global()->iconPath( QLatin1String( "folder" ), -32, false ); + } + + QString tipIcon = QString::fromLatin1( + "
\n" + " \n" + "
\n" + "
" ).arg( textDirection ) + tipIcon; + } + else + { + tip += tipIcon + QString::fromLatin1( "" ).arg( textDirection ) + tipInfo; + } + + + tip += QString::fromLatin1( + "
" + ); + + return tip; } void proxyDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); @@ -205,135 +205,135 @@ void StatisticsProxyModel::Private::proxyDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) { - if ( mExtraColumnsEnabled ) - { - // Ugly hack. - // The proper solution is a KExtraColumnsProxyModel, but this will do for now. - QModelIndex parent = topLeft.parent(); - int parentColumnCount = mParent->columnCount( parent ); - QModelIndex extraTopLeft = mParent->index( topLeft.row(), parentColumnCount - 1 - 3 , parent ); - QModelIndex extraBottomRight = mParent->index( bottomRight.row(), parentColumnCount -1, parent ); - mParent->disconnect( mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - mParent, SLOT(proxyDataChanged(QModelIndex,QModelIndex)) ); - emit mParent->dataChanged( extraTopLeft, extraBottomRight ); - - // We get this signal when the statistics of a row changes. - // However, we need to emit data changed for the statistics of all ancestor rows too - // so that recursive totals can be updated. - while ( parent.isValid() ) + if ( mExtraColumnsEnabled ) { - emit mParent->dataChanged( parent.sibling( parent.row(), parentColumnCount - 1 - 3 ), - parent.sibling( parent.row(), parentColumnCount - 1 ) ); - parent = parent.parent(); - parentColumnCount = mParent->columnCount( parent ); - } - mParent->connect( mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - SLOT(proxyDataChanged(QModelIndex,QModelIndex)) ); - } + // Ugly hack. + // The proper solution is a KExtraColumnsProxyModel, but this will do for now. + QModelIndex parent = topLeft.parent(); + int parentColumnCount = mParent->columnCount( parent ); + QModelIndex extraTopLeft = mParent->index( topLeft.row(), parentColumnCount - 1 - 3 , parent ); + QModelIndex extraBottomRight = mParent->index( bottomRight.row(), parentColumnCount -1, parent ); + mParent->disconnect( mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + mParent, SLOT(proxyDataChanged(QModelIndex,QModelIndex)) ); + emit mParent->dataChanged( extraTopLeft, extraBottomRight ); + + // We get this signal when the statistics of a row changes. + // However, we need to emit data changed for the statistics of all ancestor rows too + // so that recursive totals can be updated. + while ( parent.isValid() ) + { + emit mParent->dataChanged( parent.sibling( parent.row(), parentColumnCount - 1 - 3 ), + parent.sibling( parent.row(), parentColumnCount - 1 ) ); + parent = parent.parent(); + parentColumnCount = mParent->columnCount( parent ); + } + mParent->connect( mParent, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + SLOT(proxyDataChanged(QModelIndex,QModelIndex)) ); + } } void StatisticsProxyModel::Private::sourceLayoutAboutToBeChanged() { - // KIdentityProxyModel took care of the first columnCount() columns - // We have to take care of the extra columns (by storing persistent indexes in column 0, - // waiting for the source to update them, and then looking at where they ended up) - QModelIndexList persistent = mParent->persistentIndexList(); - const int columnCount = mParent->sourceModel()->columnCount(); - foreach( const QModelIndex &proxyPersistentIndex, persistent ) { - if ( proxyPersistentIndex.column() >= columnCount ) { - m_proxyIndexes << proxyPersistentIndex; - m_persistentSourceFirstColumn << QPersistentModelIndex( sourceIndexAtFirstColumn( proxyPersistentIndex ) ); + // KIdentityProxyModel took care of the first columnCount() columns + // We have to take care of the extra columns (by storing persistent indexes in column 0, + // waiting for the source to update them, and then looking at where they ended up) + QModelIndexList persistent = mParent->persistentIndexList(); + const int columnCount = mParent->sourceModel()->columnCount(); + foreach( const QModelIndex &proxyPersistentIndex, persistent ) { + if ( proxyPersistentIndex.column() >= columnCount ) { + m_proxyIndexes << proxyPersistentIndex; + m_persistentSourceFirstColumn << QPersistentModelIndex( sourceIndexAtFirstColumn( proxyPersistentIndex ) ); + } } - } } void StatisticsProxyModel::Private::sourceLayoutChanged() { - QModelIndexList oldList; - QModelIndexList newList; + QModelIndexList oldList; + QModelIndexList newList; - for( int i = 0; i < m_proxyIndexes.size(); ++i ) { - const QModelIndex oldProxyIndex = m_proxyIndexes.at( i ); - const QModelIndex proxyIndexFirstCol = mParent->mapFromSource( m_persistentSourceFirstColumn.at( i ) ); - const QModelIndex newProxyIndex = proxyIndexFirstCol.sibling( proxyIndexFirstCol.row(), oldProxyIndex.column() ); - if ( newProxyIndex != oldProxyIndex ) { - oldList.append( oldProxyIndex ); - newList.append( newProxyIndex ); - } - } - mParent->changePersistentIndexList( oldList, newList ); - m_persistentSourceFirstColumn.clear(); - m_proxyIndexes.clear(); + for( int i = 0; i < m_proxyIndexes.size(); ++i ) { + const QModelIndex oldProxyIndex = m_proxyIndexes.at( i ); + const QModelIndex proxyIndexFirstCol = mParent->mapFromSource( m_persistentSourceFirstColumn.at( i ) ); + const QModelIndex newProxyIndex = proxyIndexFirstCol.sibling( proxyIndexFirstCol.row(), oldProxyIndex.column() ); + if ( newProxyIndex != oldProxyIndex ) { + oldList.append( oldProxyIndex ); + newList.append( newProxyIndex ); + } + } + mParent->changePersistentIndexList( oldList, newList ); + m_persistentSourceFirstColumn.clear(); + m_proxyIndexes.clear(); } void StatisticsProxyModel::setSourceModel(QAbstractItemModel* sourceModel) { - // Order is important here. sourceLayoutChanged must be called *before* any downstreams react - // to the layoutChanged so that it can have the QPersistentModelIndexes uptodate in time. - disconnect(this, SIGNAL(layoutChanged()), this, SLOT(sourceLayoutChanged())); - connect(this, SIGNAL(layoutChanged()), SLOT(sourceLayoutChanged())); - KIdentityProxyModel::setSourceModel(sourceModel); - // This one should come *after* any downstream handlers of layoutAboutToBeChanged. - // The connectNotify stuff below ensures that it remains the last one. - disconnect(this, SIGNAL(layoutAboutToBeChanged()), this, SLOT(sourceLayoutAboutToBeChanged())); - connect(this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged())); + // Order is important here. sourceLayoutChanged must be called *before* any downstreams react + // to the layoutChanged so that it can have the QPersistentModelIndexes uptodate in time. + disconnect(this, SIGNAL(layoutChanged()), this, SLOT(sourceLayoutChanged())); + connect(this, SIGNAL(layoutChanged()), SLOT(sourceLayoutChanged())); + KIdentityProxyModel::setSourceModel(sourceModel); + // This one should come *after* any downstream handlers of layoutAboutToBeChanged. + // The connectNotify stuff below ensures that it remains the last one. + disconnect(this, SIGNAL(layoutAboutToBeChanged()), this, SLOT(sourceLayoutAboutToBeChanged())); + connect(this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged())); } void StatisticsProxyModel::connectNotify(const char *signal) { - static bool ignore = false; - if (ignore || QLatin1String(signal) == SIGNAL(layoutAboutToBeChanged())) - return KIdentityProxyModel::connectNotify(signal); - ignore = true; - disconnect(this, SIGNAL(layoutAboutToBeChanged()), this, SLOT(sourceLayoutAboutToBeChanged())); - connect(this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged())); - ignore = false; - KIdentityProxyModel::connectNotify(signal); + static bool ignore = false; + if (ignore || QLatin1String(signal) == SIGNAL(layoutAboutToBeChanged())) + return KIdentityProxyModel::connectNotify(signal); + ignore = true; + disconnect(this, SIGNAL(layoutAboutToBeChanged()), this, SLOT(sourceLayoutAboutToBeChanged())); + connect(this, SIGNAL(layoutAboutToBeChanged()), SLOT(sourceLayoutAboutToBeChanged())); + ignore = false; + KIdentityProxyModel::connectNotify(signal); } StatisticsProxyModel::StatisticsProxyModel( QObject *parent ) - : KIdentityProxyModel( parent ), - d( new Private( this ) ) + : KIdentityProxyModel( parent ), + d( new Private( this ) ) { - connect( this, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - SLOT(proxyDataChanged(QModelIndex,QModelIndex)) ); + connect( this, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + SLOT(proxyDataChanged(QModelIndex,QModelIndex)) ); } StatisticsProxyModel::~StatisticsProxyModel() { - delete d; + delete d; } void StatisticsProxyModel::setToolTipEnabled( bool enable ) { - d->mToolTipEnabled = enable; + d->mToolTipEnabled = enable; } bool StatisticsProxyModel::isToolTipEnabled() const { - return d->mToolTipEnabled; + return d->mToolTipEnabled; } void StatisticsProxyModel::setExtraColumnsEnabled( bool enable ) { - d->mExtraColumnsEnabled = enable; + d->mExtraColumnsEnabled = enable; } bool StatisticsProxyModel::isExtraColumnsEnabled() const { - return d->mExtraColumnsEnabled; + return d->mExtraColumnsEnabled; } QModelIndex StatisticsProxyModel::index( int row, int column, const QModelIndex & parent ) const { if (!hasIndex(row, column, parent)) - return QModelIndex(); + return QModelIndex(); int sourceColumn = column; if ( column >= d->sourceColumnCount() ) { - sourceColumn = 0; + sourceColumn = 0; } QModelIndex i = KIdentityProxyModel::index( row, sourceColumn, parent ); @@ -343,7 +343,7 @@ struct SourceModelIndex { SourceModelIndex(int _r, int _c, void *_p, QAbstractItemModel *_m) - : r(_r), c(_c), p(_p), m(_m) {} + : r(_r), c(_c), p(_p), m(_m) {} operator QModelIndex() { return reinterpret_cast(*this); } @@ -354,168 +354,168 @@ QModelIndex StatisticsProxyModel::Private::sourceIndexAtFirstColumn(const QModelIndex& proxyIndex) const { - // We rely on the fact that the internal pointer is the same for column 0 and for the extra columns - return SourceModelIndex(proxyIndex.row(), 0, proxyIndex.internalPointer(), mParent->sourceModel()); + // We rely on the fact that the internal pointer is the same for column 0 and for the extra columns + return SourceModelIndex(proxyIndex.row(), 0, proxyIndex.internalPointer(), mParent->sourceModel()); } QModelIndex StatisticsProxyModel::parent(const QModelIndex& child) const { - if (!sourceModel()) - return QModelIndex(); + if (!sourceModel()) + return QModelIndex(); - Q_ASSERT(child.isValid() ? child.model() == this : true); - if (child.column() >= d->sourceColumnCount()) { - // We need to get hold of the source index at column 0. But we can't do that - // via the proxy index at column 0, because sibling() or index() needs the - // parent index, and that's *exactly* what we're trying to determine here. - // So the only way is to create a source index ourselves. - const QModelIndex sourceIndex = d->sourceIndexAtFirstColumn(child); - const QModelIndex sourceParent = sourceIndex.parent(); - //kDebug() << "parent of" << child.data() << "is" << sourceParent.data(); - return mapFromSource(sourceParent); - } else { - return KIdentityProxyModel::parent(child); - } + Q_ASSERT(child.isValid() ? child.model() == this : true); + if (child.column() >= d->sourceColumnCount()) { + // We need to get hold of the source index at column 0. But we can't do that + // via the proxy index at column 0, because sibling() or index() needs the + // parent index, and that's *exactly* what we're trying to determine here. + // So the only way is to create a source index ourselves. + const QModelIndex sourceIndex = d->sourceIndexAtFirstColumn(child); + const QModelIndex sourceParent = sourceIndex.parent(); + //kDebug() << "parent of" << child.data() << "is" << sourceParent.data(); + return mapFromSource(sourceParent); + } else { + return KIdentityProxyModel::parent(child); + } } QVariant StatisticsProxyModel::data( const QModelIndex & index, int role) const { - if (!sourceModel()) - return QVariant(); + if (!sourceModel()) + return QVariant(); - const int sourceColumnCount = d->sourceColumnCount(); + const int sourceColumnCount = d->sourceColumnCount(); - if ( role == Qt::DisplayRole && index.column() >= sourceColumnCount ) { - const QModelIndex sourceIndex = d->sourceIndexAtFirstColumn( index ); - Collection collection = sourceModel()->data( sourceIndex, EntityTreeModel::CollectionRole ).value(); - - if ( collection.isValid() && collection.statistics().count()>=0 ) { - if ( index.column() == sourceColumnCount + 2 ) { - return KIO::convertSize( (KIO::filesize_t)( collection.statistics().size() ) ); - } else if ( index.column() == sourceColumnCount + 1 ) { - return collection.statistics().count(); - } else if ( index.column() == sourceColumnCount ) { - if ( collection.statistics().unreadCount() > 0 ) { - return collection.statistics().unreadCount(); - } else { - return QString(); + if ( role == Qt::DisplayRole && index.column() >= sourceColumnCount ) { + const QModelIndex sourceIndex = d->sourceIndexAtFirstColumn( index ); + Collection collection = sourceModel()->data( sourceIndex, EntityTreeModel::CollectionRole ).value(); + + if ( collection.isValid() && collection.statistics().count()>=0 ) { + if ( index.column() == sourceColumnCount + 2 ) { + return KIO::convertSize( (KIO::filesize_t)( collection.statistics().size() ) ); + } else if ( index.column() == sourceColumnCount + 1 ) { + return collection.statistics().count(); + } else if ( index.column() == sourceColumnCount ) { + if ( collection.statistics().unreadCount() > 0 ) { + return collection.statistics().unreadCount(); + } else { + return QString(); + } + } else { + kWarning() << "We shouldn't get there for a column which is not total, unread or size."; + return QVariant(); + } } - } else { - kWarning() << "We shouldn't get there for a column which is not total, unread or size."; - return QVariant(); - } - } - } else if ( role == Qt::TextAlignmentRole && index.column() >= sourceColumnCount ) { - return Qt::AlignRight; + } else if ( role == Qt::TextAlignmentRole && index.column() >= sourceColumnCount ) { + return Qt::AlignRight; - } else if ( role == Qt::ToolTipRole && d->mToolTipEnabled ) { - const QModelIndex sourceIndex = d->sourceIndexAtFirstColumn( index ); - Collection collection - = sourceModel()->data( sourceIndex, - EntityTreeModel::CollectionRole ).value(); + } else if ( role == Qt::ToolTipRole && d->mToolTipEnabled ) { + const QModelIndex sourceIndex = d->sourceIndexAtFirstColumn( index ); + Collection collection + = sourceModel()->data( sourceIndex, + EntityTreeModel::CollectionRole ).value(); + + if ( collection.isValid() ) { + const QModelIndex sourceIndex = d->sourceIndexAtFirstColumn( index ); + return d->toolTipForCollection( sourceIndex, collection ); + } - if ( collection.isValid() ) { - const QModelIndex sourceIndex = d->sourceIndexAtFirstColumn( index ); - return d->toolTipForCollection( sourceIndex, collection ); + } else if ( role == Qt::DecorationRole && index.column() == 0 ) { + const QModelIndex sourceIndex = mapToSource( index ); + Collection collection = sourceModel()->data( sourceIndex, EntityTreeModel::CollectionRole ).value(); + if ( collection.isValid() ) + return KIcon( CollectionUtils::displayIconName( collection ) ); + else + return QVariant(); } - } else if ( role == Qt::DecorationRole && index.column() == 0 ) { - const QModelIndex sourceIndex = mapToSource( index ); - Collection collection = sourceModel()->data( sourceIndex, EntityTreeModel::CollectionRole ).value(); - if ( collection.isValid() ) - return KIcon( CollectionUtils::displayIconName( collection ) ); - else - return QVariant(); - } - - if ( index.column() >= sourceColumnCount ) - return QVariant(); + if ( index.column() >= sourceColumnCount ) + return QVariant(); - return QAbstractProxyModel::data( index, role ); + return QAbstractProxyModel::data( index, role ); } QVariant StatisticsProxyModel::headerData( int section, Qt::Orientation orientation, int role) const { - if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) { - if ( section == d->sourceColumnCount() + 2 ) { - return i18nc( "collection size", "Size" ); - } else if ( section == d->sourceColumnCount() + 1 ) { - return i18nc( "number of entities in the collection", "Total" ); - } else if ( section == d->sourceColumnCount() ) { - return i18nc( "number of unread entities in the collection", "Unread" ); - } - } - - if ( orientation == Qt::Horizontal && section >= d->sourceColumnCount() ) { - return QVariant(); - } + if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) { + if ( section == d->sourceColumnCount() + 2 ) { + return i18nc( "collection size", "Size" ); + } else if ( section == d->sourceColumnCount() + 1 ) { + return i18nc( "number of entities in the collection", "Total" ); + } else if ( section == d->sourceColumnCount() ) { + return i18nc( "number of unread entities in the collection", "Unread" ); + } + } + + if ( orientation == Qt::Horizontal && section >= d->sourceColumnCount() ) { + return QVariant(); + } - return KIdentityProxyModel::headerData( section, orientation, role ); + return KIdentityProxyModel::headerData( section, orientation, role ); } Qt::ItemFlags StatisticsProxyModel::flags( const QModelIndex & index ) const { - if ( index.column() >= d->sourceColumnCount() ) { - return KIdentityProxyModel::flags( index.sibling( index.row(), 0 ) ) - & ( Qt::ItemIsSelectable | Qt::ItemIsDragEnabled // Allowed flags - | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled ); - } + if ( index.column() >= d->sourceColumnCount() ) { + return KIdentityProxyModel::flags( index.sibling( index.row(), 0 ) ) + & ( Qt::ItemIsSelectable | Qt::ItemIsDragEnabled // Allowed flags + | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled ); + } - return KIdentityProxyModel::flags( index ); + return KIdentityProxyModel::flags( index ); } int StatisticsProxyModel::columnCount( const QModelIndex & /*parent*/ ) const { - if ( sourceModel()==0 ) { - return 0; - } else { - return d->sourceColumnCount() - + ( d->mExtraColumnsEnabled ? 3 : 0 ); - } + if ( sourceModel()==0 ) { + return 0; + } else { + return d->sourceColumnCount() + + ( d->mExtraColumnsEnabled ? 3 : 0 ); + } } QModelIndexList StatisticsProxyModel::match( const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags ) const { - if ( role < Qt::UserRole ) - return KIdentityProxyModel::match( start, role, value, hits, flags ); + if ( role < Qt::UserRole ) + return KIdentityProxyModel::match( start, role, value, hits, flags ); - QModelIndexList list; - QModelIndex proxyIndex; - foreach ( const QModelIndex &idx, sourceModel()->match( mapToSource( start ), role, value, hits, flags ) ) { - proxyIndex = mapFromSource( idx ); - if ( proxyIndex.isValid() ) - list << proxyIndex; - } + QModelIndexList list; + QModelIndex proxyIndex; + foreach ( const QModelIndex &idx, sourceModel()->match( mapToSource( start ), role, value, hits, flags ) ) { + proxyIndex = mapFromSource( idx ); + if ( proxyIndex.isValid() ) + list << proxyIndex; + } - return list; + return list; } QModelIndex StatisticsProxyModel::mapFromSource(const QModelIndex& sourceIndex) const { - if (!sourceIndex.isValid()) - return QModelIndex(); - Q_ASSERT(sourceIndex.model() == sourceModel()); - Q_ASSERT(sourceIndex.column() < d->sourceColumnCount()); - return KIdentityProxyModel::mapFromSource(sourceIndex); + if (!sourceIndex.isValid()) + return QModelIndex(); + Q_ASSERT(sourceIndex.model() == sourceModel()); + Q_ASSERT(sourceIndex.column() < d->sourceColumnCount()); + return KIdentityProxyModel::mapFromSource(sourceIndex); } QModelIndex StatisticsProxyModel::mapToSource(const QModelIndex& index) const { - if (!index.isValid()) - return QModelIndex(); - Q_ASSERT(index.model() == this); - if (index.column() >= d->sourceColumnCount() ) { - return QModelIndex(); - } - return KIdentityProxyModel::mapToSource(index); + if (!index.isValid()) + return QModelIndex(); + Q_ASSERT(index.model() == this); + if (index.column() >= d->sourceColumnCount() ) { + return QModelIndex(); + } + return KIdentityProxyModel::mapToSource(index); } QModelIndex StatisticsProxyModel::buddy(const QModelIndex &index) const { - Q_UNUSED(index); - return QModelIndex(); + Q_UNUSED(index); + return QModelIndex(); } QItemSelection StatisticsProxyModel::mapSelectionToSource(const QItemSelection& selection) const @@ -523,7 +523,7 @@ QItemSelection sourceSelection; if (!sourceModel()) - return sourceSelection; + return sourceSelection; // mapToSource will give invalid index for our additional columns, so truncate the selection // to the columns known by the source model @@ -540,7 +540,7 @@ Q_ASSERT(bottomRight.isValid()); Q_ASSERT(bottomRight.model() == this); if (bottomRight.column() >= sourceColumnCount) - bottomRight = bottomRight.sibling(bottomRight.row(), sourceColumnCount-1); + bottomRight = bottomRight.sibling(bottomRight.row(), sourceColumnCount-1); // This can lead to duplicate source indexes, so use merge(). const QItemSelectionRange range(mapToSource(topLeft), mapToSource(bottomRight)); QItemSelection newSelection; newSelection << range; diff -Nru kdepim-4.12.97/libkdepim/misc/statisticsproxymodel.h kdepim-4.13.0/libkdepim/misc/statisticsproxymodel.h --- kdepim-4.12.97/libkdepim/misc/statisticsproxymodel.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/misc/statisticsproxymodel.h 2014-04-10 07:40:20.000000000 +0000 @@ -49,9 +49,9 @@ */ class KDEPIM_EXPORT StatisticsProxyModel : public KIdentityProxyModel { - Q_OBJECT + Q_OBJECT - public: +public: /** * Creates a new statistics proxy model. * @@ -104,7 +104,7 @@ QItemSelection mapSelectionToSource(const QItemSelection& selection) const; - private: +private: //@cond PRIVATE class Private; Private* const d; diff -Nru kdepim-4.12.97/libkdepim/misc/uistatesaver.cpp kdepim-4.13.0/libkdepim/misc/uistatesaver.cpp --- kdepim-4.12.97/libkdepim/misc/uistatesaver.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/misc/uistatesaver.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -30,90 +30,90 @@ using namespace KPIM; struct Saver { - static void process( QSplitter *splitter, KConfigGroup &config ) - { - if ( splitter->sizes().count( 0 ) == splitter->sizes().count() ) - return; - config.writeEntry( splitter->objectName(), splitter->sizes() ); - } - - static void process( QTabWidget *tab, KConfigGroup &config ) - { - config.writeEntry( tab->objectName(), tab->currentIndex() ); - } - - static void process( QTreeView *tv, KConfigGroup &config ) - { - config.writeEntry( tv->objectName(), tv->header()->saveState() ); - } - - static void process( QComboBox *cb, KConfigGroup &config ) - { - config.writeEntry( cb->objectName(), cb->currentIndex() ); - } + static void process( QSplitter *splitter, KConfigGroup &config ) + { + if ( splitter->sizes().count( 0 ) == splitter->sizes().count() ) + return; + config.writeEntry( splitter->objectName(), splitter->sizes() ); + } + + static void process( QTabWidget *tab, KConfigGroup &config ) + { + config.writeEntry( tab->objectName(), tab->currentIndex() ); + } + + static void process( QTreeView *tv, KConfigGroup &config ) + { + config.writeEntry( tv->objectName(), tv->header()->saveState() ); + } + + static void process( QComboBox *cb, KConfigGroup &config ) + { + config.writeEntry( cb->objectName(), cb->currentIndex() ); + } }; struct Restorer { - static void process( QSplitter *splitter, const KConfigGroup &config ) - { - const QList sizes = config.readEntry( splitter->objectName(), QList() ); - if ( !sizes.isEmpty() && splitter->count() == sizes.count() && sizes.count() != sizes.count( 0 ) ) - splitter->setSizes( sizes ); - } - - static void process( QTabWidget *tab, const KConfigGroup &config ) - { - const int index = config.readEntry( tab->objectName(), -1 ); - if ( index >= 0 && index < tab->count() ) - tab->setCurrentIndex( index ); - } - - static void process( QTreeView *tv, const KConfigGroup &config ) - { - const QByteArray state = config.readEntry( tv->objectName(), QByteArray() ); - if ( !state.isEmpty() ) - tv->header()->restoreState( state ); - } - - static void process( QComboBox *cb, const KConfigGroup &config ) - { - const int index = config.readEntry( cb->objectName(), -1 ); - if ( index >= 0 && index < cb->count() ) - cb->setCurrentIndex( index ); - } + static void process( QSplitter *splitter, const KConfigGroup &config ) + { + const QList sizes = config.readEntry( splitter->objectName(), QList() ); + if ( !sizes.isEmpty() && splitter->count() == sizes.count() && sizes.count() != sizes.count( 0 ) ) + splitter->setSizes( sizes ); + } + + static void process( QTabWidget *tab, const KConfigGroup &config ) + { + const int index = config.readEntry( tab->objectName(), -1 ); + if ( index >= 0 && index < tab->count() ) + tab->setCurrentIndex( index ); + } + + static void process( QTreeView *tv, const KConfigGroup &config ) + { + const QByteArray state = config.readEntry( tv->objectName(), QByteArray() ); + if ( !state.isEmpty() ) + tv->header()->restoreState( state ); + } + + static void process( QComboBox *cb, const KConfigGroup &config ) + { + const int index = config.readEntry( cb->objectName(), -1 ); + if ( index >= 0 && index < cb->count() ) + cb->setCurrentIndex( index ); + } }; #define PROCESS_TYPE( T ) \ { \ - T *obj = qobject_cast( w ); \ - if ( obj ) { \ + T *obj = qobject_cast( w ); \ + if ( obj ) { \ Op::process( obj, config ); \ continue; \ - } \ -} + } \ + } template static void processWidgets( QWidget *widget, Config config ) { - QList widgets = widget->findChildren(); - widgets << widget; - foreach ( QWidget* w, widgets ) { - if ( w->objectName().isEmpty() ) - continue; - PROCESS_TYPE( QSplitter ); - PROCESS_TYPE( QTabWidget ); - PROCESS_TYPE( QTreeView ); - PROCESS_TYPE( QComboBox ); - } + QList widgets = widget->findChildren(); + widgets << widget; + foreach ( QWidget* w, widgets ) { + if ( w->objectName().isEmpty() ) + continue; + PROCESS_TYPE( QSplitter ); + PROCESS_TYPE( QTabWidget ); + PROCESS_TYPE( QTreeView ); + PROCESS_TYPE( QComboBox ); + } } #undef PROCESS_TYPE void UiStateSaver::saveState(QWidget * widget, KConfigGroup & config) { - processWidgets( widget, config ); + processWidgets( widget, config ); } void UiStateSaver::restoreState(QWidget * widget, const KConfigGroup & config) { - processWidgets( widget, config ); + processWidgets( widget, config ); } diff -Nru kdepim-4.12.97/libkdepim/misc/uistatesaver.h kdepim-4.13.0/libkdepim/misc/uistatesaver.h --- kdepim-4.12.97/libkdepim/misc/uistatesaver.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/misc/uistatesaver.h 2014-04-10 07:40:20.000000000 +0000 @@ -47,19 +47,19 @@ */ namespace UiStateSaver { - /** +/** * Saves the state of @p widget and all its sub-widgets to @p config. * @param widget The top-level widget which state should be saved. * @param config The config group the settings should be written to. */ - KDEPIM_EXPORT void saveState( QWidget* widget, KConfigGroup &config ); +KDEPIM_EXPORT void saveState( QWidget* widget, KConfigGroup &config ); - /** +/** * Restores the UI state of @p widget and all its sub-widgets from @p config. * @param widget The top-level widget which state should be restored. * @param config The config gorup the settings should be read from. */ - KDEPIM_EXPORT void restoreState( QWidget *widget, const KConfigGroup &config ); +KDEPIM_EXPORT void restoreState( QWidget *widget, const KConfigGroup &config ); } } diff -Nru kdepim-4.12.97/libkdepim/multiplyingline/multiplyingline.cpp kdepim-4.13.0/libkdepim/multiplyingline/multiplyingline.cpp --- kdepim-4.12.97/libkdepim/multiplyingline/multiplyingline.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/multiplyingline/multiplyingline.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -34,31 +34,31 @@ void MultiplyingLine::slotReturnPressed() { - emit returnPressed( this ); + emit returnPressed( this ); } void MultiplyingLine::slotPropagateDeletion() { - emit deleteLine( this ); + emit deleteLine( this ); } void MultiplyingLine::slotFocusUp() { - emit upPressed( this ); + emit upPressed( this ); } void MultiplyingLine::slotFocusDown() { - emit downPressed( this ); + emit downPressed( this ); } void MultiplyingLine::keyPressEvent( QKeyEvent* ev ) { - if ( ev->key() == Qt::Key_Up ) { - emit upPressed( this ); - } else if ( ev->key() == Qt::Key_Down ) { - emit downPressed( this ); - } + if ( ev->key() == Qt::Key_Up ) { + emit upPressed( this ); + } else if ( ev->key() == Qt::Key_Down ) { + emit downPressed( this ); + } } void MultiplyingLine::aboutToBeDeleted() diff -Nru kdepim-4.12.97/libkdepim/multiplyingline/multiplyinglineeditor.cpp kdepim-4.13.0/libkdepim/multiplyingline/multiplyinglineeditor.cpp --- kdepim-4.12.97/libkdepim/multiplyingline/multiplyinglineeditor.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/multiplyingline/multiplyinglineeditor.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -31,134 +31,138 @@ #include using namespace KPIM; MultiplyingLineEditor::MultiplyingLineEditor( MultiplyingLineFactory* factory, QWidget *parent ) - : QWidget( parent ), mModified( false ), mMultiplyingLineFactory( factory ) + : QWidget( parent ), mModified( false ), mMultiplyingLineFactory( factory ) { - QBoxLayout *topLayout = new QHBoxLayout(); - topLayout->setSpacing( KDialog::spacingHint() ); - topLayout->setMargin( 0 ); - setLayout( topLayout ); - - mView = new MultiplyingLineView( mMultiplyingLineFactory, this ); - topLayout->addWidget( mView ); - connect( mView, SIGNAL(focusUp()), SIGNAL(focusUp()) ); - connect( mView, SIGNAL(focusDown()), SIGNAL(focusDown()) ); - connect( mView, SIGNAL(completionModeChanged(KGlobalSettings::Completion)), - SIGNAL(completionModeChanged(KGlobalSettings::Completion)) ); - connect( mView, SIGNAL(lineDeleted(int)), SIGNAL(lineDeleted(int)) ); - connect( mView, SIGNAL(lineAdded(KPIM::MultiplyingLine*)), SIGNAL(lineAdded(KPIM::MultiplyingLine*)) ); - connect( mView, SIGNAL(sizeHintChanged()), - SIGNAL(sizeHintChanged()) ); + QBoxLayout *topLayout = new QHBoxLayout(); + topLayout->setSpacing( KDialog::spacingHint() ); + topLayout->setMargin( 0 ); + setLayout( topLayout ); + + mView = new MultiplyingLineView( mMultiplyingLineFactory, this ); + topLayout->addWidget( mView ); + connect( mView, SIGNAL(focusUp()), SIGNAL(focusUp()) ); + connect( mView, SIGNAL(focusDown()), SIGNAL(focusDown()) ); + connect( mView, SIGNAL(completionModeChanged(KGlobalSettings::Completion)), + SIGNAL(completionModeChanged(KGlobalSettings::Completion)) ); + connect( mView, SIGNAL(lineDeleted(int)), SIGNAL(lineDeleted(int)) ); + connect( mView, SIGNAL(lineAdded(KPIM::MultiplyingLine*)), SIGNAL(lineAdded(KPIM::MultiplyingLine*)) ); + connect( mView, SIGNAL(sizeHintChanged()), + SIGNAL(sizeHintChanged()) ); } MultiplyingLineEditor::~MultiplyingLineEditor() { - delete mMultiplyingLineFactory; + delete mMultiplyingLineFactory; } -void MultiplyingLineEditor::addData( const MultiplyingLineData::Ptr &data ) +bool MultiplyingLineEditor::addData( const MultiplyingLineData::Ptr &data ) { - MultiplyingLine* line = mView->emptyLine(); - if( !line ) - line = mView->addLine(); - if( line && data ) - line->setData( data ); + MultiplyingLine* line = mView->emptyLine(); + bool tooManyAddress = false; + if( !line ) + line = mView->addLine(); + if (!line) + tooManyAddress = true; + if( line && data ) + line->setData( data ); + return tooManyAddress; } void MultiplyingLineEditor::removeData( const MultiplyingLineData::Ptr &data ) { - mView->removeData( data ); + mView->removeData( data ); } void MultiplyingLineEditor::clear() { - foreach ( MultiplyingLine *line, mView->lines() ) - line->slotPropagateDeletion(); + foreach ( MultiplyingLine *line, mView->lines() ) + line->slotPropagateDeletion(); } bool MultiplyingLineEditor::isModified() { - return mModified || mView->isModified(); + return mModified || mView->isModified(); } void MultiplyingLineEditor::clearModified() { - mModified = false; - mView->clearModified(); + mModified = false; + mView->clearModified(); } void MultiplyingLineEditor::setFocus() { - mView->setFocus(); + mView->setFocus(); } void MultiplyingLineEditor::setFocusTop() { - mView->setFocusTop(); + mView->setFocusTop(); } void MultiplyingLineEditor::setFocusBottom() { - mView->setFocusBottom(); + mView->setFocusBottom(); } int MultiplyingLineEditor::setFirstColumnWidth( int w ) { - return mView->setFirstColumnWidth( w ); + return mView->setFirstColumnWidth( w ); } void MultiplyingLineEditor::setCompletionMode( KGlobalSettings::Completion mode ) { - mView->setCompletionMode( mode ); + mView->setCompletionMode( mode ); } MultiplyingLineFactory* MultiplyingLineEditor::factory() const { - return mMultiplyingLineFactory; + return mMultiplyingLineFactory; } QList< MultiplyingLineData::Ptr > MultiplyingLineEditor::allData() const { - return mView->allData(); + return mView->allData(); } MultiplyingLineData::Ptr MultiplyingLineEditor::activeData() const { - return mView->activeLine()->data(); + return mView->activeLine()->data(); } QList< MultiplyingLine* > MultiplyingLineEditor::lines() const { - return mView->lines(); + return mView->lines(); } MultiplyingLine* MultiplyingLineEditor::activeLine() const { - return mView->activeLine(); + return mView->activeLine(); } void MultiplyingLineEditor::setFrameStyle( int shape ) { - mView->setFrameStyle( shape ); + mView->setFrameStyle( shape ); } void MultiplyingLineEditor::setAutoResizeView( bool resize ) { - mView->setAutoResize( resize ); + mView->setAutoResize( resize ); } bool MultiplyingLineEditor::autoResizeView() { - return mView->autoResize(); + return mView->autoResize(); } void MultiplyingLineEditor::setDynamicSizeHint( bool dynamic ) { - mView->setDynamicSizeHint( dynamic ); + mView->setDynamicSizeHint( dynamic ); } bool MultiplyingLineEditor::dynamicSizeHint() const { - return mView->dynamicSizeHint(); + return mView->dynamicSizeHint(); } diff -Nru kdepim-4.12.97/libkdepim/multiplyingline/multiplyinglineeditor.h kdepim-4.13.0/libkdepim/multiplyingline/multiplyinglineeditor.h --- kdepim-4.12.97/libkdepim/multiplyingline/multiplyinglineeditor.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/multiplyingline/multiplyinglineeditor.h 2014-04-10 07:40:20.000000000 +0000 @@ -44,8 +44,8 @@ */ class KDEPIM_EXPORT MultiplyingLineFactory : public QObject { - Q_OBJECT - public: + Q_OBJECT +public: explicit MultiplyingLineFactory( QObject* parent ) : QObject( parent ) {} virtual ~MultiplyingLineFactory() {} virtual MultiplyingLine* newLine( QWidget *parent ) = 0; @@ -72,11 +72,11 @@ */ class KDEPIM_EXPORT MultiplyingLineEditor : public QWidget { - Q_OBJECT - Q_PROPERTY( bool autoResizeView READ autoResizeView WRITE setAutoResizeView ) - Q_PROPERTY( bool dynamicSizeHint READ dynamicSizeHint WRITE setDynamicSizeHint ) + Q_OBJECT + Q_PROPERTY( bool autoResizeView READ autoResizeView WRITE setAutoResizeView ) + Q_PROPERTY( bool dynamicSizeHint READ dynamicSizeHint WRITE setDynamicSizeHint ) - public: +public: // We take ownership of factory explicit MultiplyingLineEditor( MultiplyingLineFactory* factory, QWidget *parent = 0 ); @@ -110,7 +110,7 @@ @param data The data you want to add. Can be used to add an empty/default line. */ - void addData( const MultiplyingLineData::Ptr &data = MultiplyingLineData::Ptr() ); + bool addData( const MultiplyingLineData::Ptr &data = MultiplyingLineData::Ptr() ); /** Removes data provided it can be found. The Data class must support operator== @param data The data you want to add. @@ -152,7 +152,7 @@ void setDynamicSizeHint( bool dynamic ); bool dynamicSizeHint() const; - signals: +signals: void focusUp(); void focusDown(); void completionModeChanged( KGlobalSettings::Completion ); @@ -160,17 +160,17 @@ void lineDeleted( int pos ); void lineAdded( KPIM::MultiplyingLine * ); - public slots: +public slots: void setFocus(); void setFocusTop(); void setFocusBottom(); - protected: +protected: virtual QList lines() const; virtual MultiplyingLine *activeLine() const; bool mModified; - private: +private: MultiplyingLineFactory *mMultiplyingLineFactory; MultiplyingLineView *mView; }; diff -Nru kdepim-4.12.97/libkdepim/multiplyingline/multiplyingline.h kdepim-4.13.0/libkdepim/multiplyingline/multiplyingline.h --- kdepim-4.12.97/libkdepim/multiplyingline/multiplyingline.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/multiplyingline/multiplyingline.h 2014-04-10 07:40:20.000000000 +0000 @@ -40,7 +40,7 @@ */ class KDEPIM_EXPORT MultiplyingLineData { - public: +public: typedef QSharedPointer Ptr; virtual ~MultiplyingLineData(){} @@ -65,7 +65,7 @@ { Q_OBJECT - public: +public: explicit MultiplyingLine( QWidget *parent ); virtual ~MultiplyingLine() {} @@ -178,7 +178,7 @@ */ virtual void aboutToBeDeleted(); - signals: +signals: /** Emitted when the return/enter key is pressed */ @@ -203,16 +203,16 @@ Emitted when the completion mode changes */ void completionModeChanged( KGlobalSettings::Completion ); - public slots: +public slots: void slotPropagateDeletion(); - protected slots: +protected slots: void slotReturnPressed(); void slotFocusUp(); void slotFocusDown(); - protected: +protected: /** Handles key press events on this line. Default behavior handles Up and Down presses. diff -Nru kdepim-4.12.97/libkdepim/multiplyingline/multiplyinglineview_p.cpp kdepim-4.13.0/libkdepim/multiplyingline/multiplyinglineview_p.cpp --- kdepim-4.12.97/libkdepim/multiplyingline/multiplyinglineview_p.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/multiplyingline/multiplyinglineview_p.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -33,383 +33,384 @@ #include using namespace KPIM; - + MultiplyingLineView::MultiplyingLineView( MultiplyingLineFactory* factory, MultiplyingLineEditor *parent ) - : QScrollArea( parent ), mCurDelLine( 0 ), - mLineHeight( 0 ), mFirstColumnWidth( 0 ), - mModified( false ), mCompletionMode( KGlobalSettings::completionMode() ), - mPage( new QWidget( this ) ), mTopLayout( new QVBoxLayout( this ) ), - mMultiplyingLineFactory( factory ), mAutoResize( false ), mDynamicSizeHint( true ) -{ - setWidgetResizable( true ); - setFrameStyle( QFrame::NoFrame ); - - mPage->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); - setWidget( mPage ); - - mTopLayout->setMargin( 0 ); - mTopLayout->setSpacing( 0 ); - mPage->setLayout( mTopLayout ); + : QScrollArea( parent ), mCurDelLine( 0 ), + mLineHeight( 0 ), mFirstColumnWidth( 0 ), + mModified( false ), mCompletionMode( KGlobalSettings::completionMode() ), + mPage( new QWidget( this ) ), mTopLayout( new QVBoxLayout( this ) ), + mMultiplyingLineFactory( factory ), mAutoResize( false ), mDynamicSizeHint( true ) +{ + setWidgetResizable( true ); + setFrameStyle( QFrame::NoFrame ); + + mPage->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + setWidget( mPage ); + + mTopLayout->setMargin( 0 ); + mTopLayout->setSpacing( 0 ); + mPage->setLayout( mTopLayout ); } MultiplyingLine* MultiplyingLineView::activeLine() const { - return mLines.last(); + return mLines.last(); } MultiplyingLine* MultiplyingLineView::emptyLine() const { - foreach( MultiplyingLine* line, mLines ) { - if ( line->isEmpty() ) - return line; - } - return 0; + foreach( MultiplyingLine* line, mLines ) { + if ( line->isEmpty() ) + return line; + } + return 0; } MultiplyingLine* MultiplyingLineView::addLine() { - const int maximumRecipients = mMultiplyingLineFactory->maximumRecipients(); - if (maximumRecipients != -1) { - int numberOfLine = mLines.count(); - if (numberOfLine++ >= maximumRecipients) { - KMessageBox::sorry( this, - i18n("We can not add more recipients. We have reached maximum recipients")); - - return 0; - } - } - MultiplyingLine* line = mMultiplyingLineFactory->newLine( widget() ); - - mTopLayout->addWidget( line ); - line->setCompletionMode( mCompletionMode ); - line->show(); - connect( line, SIGNAL(returnPressed(KPIM::MultiplyingLine*)), - SLOT(slotReturnPressed(KPIM::MultiplyingLine*)) ); - connect( line, SIGNAL(upPressed(KPIM::MultiplyingLine*)), - SLOT(slotUpPressed(KPIM::MultiplyingLine*)) ); - connect( line, SIGNAL(downPressed(KPIM::MultiplyingLine*)), - SLOT(slotDownPressed(KPIM::MultiplyingLine*)) ); - connect( line, SIGNAL(rightPressed()), SIGNAL(focusRight()) ); - connect( line, SIGNAL(deleteLine(KPIM::MultiplyingLine*)), - SLOT(slotDecideLineDeletion(KPIM::MultiplyingLine*)) ); - connect( line, SIGNAL(completionModeChanged(KGlobalSettings::Completion)), - SLOT(setCompletionMode(KGlobalSettings::Completion)) ); - - if( !mLines.isEmpty() ) { - line->fixTabOrder( mLines.last()->tabOut() ); - } - mLines.append( line ); - mFirstColumnWidth = line->setColumnWidth( mFirstColumnWidth ); - mLineHeight = line->minimumSizeHint().height(); - line->resize( viewport()->width(), mLineHeight ); - resizeView(); - ensureVisible( 0, mLines.count() * mLineHeight, 0, 0 ); + const int maximumRecipients = mMultiplyingLineFactory->maximumRecipients(); + if (maximumRecipients != -1) { + int numberOfLine = mLines.count(); + if (numberOfLine++ >= maximumRecipients) { + KMessageBox::sorry( this, + i18n("We can not add more recipients. We have reached maximum recipients")); + + return 0; + } + } + MultiplyingLine* line = mMultiplyingLineFactory->newLine( widget() ); + + mTopLayout->addWidget( line ); + line->setCompletionMode( mCompletionMode ); + line->show(); + connect( line, SIGNAL(returnPressed(KPIM::MultiplyingLine*)), + SLOT(slotReturnPressed(KPIM::MultiplyingLine*)) ); + connect( line, SIGNAL(upPressed(KPIM::MultiplyingLine*)), + SLOT(slotUpPressed(KPIM::MultiplyingLine*)) ); + connect( line, SIGNAL(downPressed(KPIM::MultiplyingLine*)), + SLOT(slotDownPressed(KPIM::MultiplyingLine*)) ); + connect( line, SIGNAL(rightPressed()), SIGNAL(focusRight()) ); + connect( line, SIGNAL(deleteLine(KPIM::MultiplyingLine*)), + SLOT(slotDecideLineDeletion(KPIM::MultiplyingLine*)) ); + connect( line, SIGNAL(completionModeChanged(KGlobalSettings::Completion)), + SLOT(setCompletionMode(KGlobalSettings::Completion)) ); - QTimer::singleShot( 0, this, SLOT(moveScrollBarToEnd()) ); + if( !mLines.isEmpty() ) { + line->fixTabOrder( mLines.last()->tabOut() ); + } + mLines.append( line ); + mFirstColumnWidth = line->setColumnWidth( mFirstColumnWidth ); + mLineHeight = line->minimumSizeHint().height(); + line->resize( viewport()->width(), mLineHeight ); + resizeView(); + ensureVisible( 0, mLines.count() * mLineHeight, 0, 0 ); + + QTimer::singleShot( 0, this, SLOT(moveScrollBarToEnd()) ); - emit lineAdded( line ); - return line; + emit lineAdded( line ); + return line; } void MultiplyingLineView::moveScrollBarToEnd() { -// scroll to bottom - verticalScrollBar()->triggerAction( QAbstractSlider::SliderToMaximum ); + // scroll to bottom + verticalScrollBar()->triggerAction( QAbstractSlider::SliderToMaximum ); } void MultiplyingLineView::slotReturnPressed( MultiplyingLine *line ) { - if ( !line->data()->isEmpty() ) { - MultiplyingLine *empty = emptyLine(); - if ( !empty ) empty = addLine(); - activateLine( empty ); - } + if ( !line->data()->isEmpty() ) { + MultiplyingLine *empty = emptyLine(); + if ( !empty ) + empty = addLine(); + activateLine( empty ); + } } void MultiplyingLineView::slotDownPressed( MultiplyingLine *line ) { - int pos = mLines.indexOf( line ); - if ( pos >= (int)mLines.count() - 1 ) { - emit focusDown(); - } else if ( pos >= 0 ) { - activateLine( mLines.at( pos + 1 ) ); - } + int pos = mLines.indexOf( line ); + if ( pos >= (int)mLines.count() - 1 ) { + emit focusDown(); + } else if ( pos >= 0 ) { + activateLine( mLines.at( pos + 1 ) ); + } } void MultiplyingLineView::slotUpPressed( MultiplyingLine *line ) { - int pos = mLines.indexOf( line ); - if ( pos > 0 ) { - activateLine( mLines.at( pos - 1 ) ); - } else { - emit focusUp(); - } + int pos = mLines.indexOf( line ); + if ( pos > 0 ) { + activateLine( mLines.at( pos - 1 ) ); + } else { + emit focusUp(); + } } void MultiplyingLineView::slotDecideLineDeletion( MultiplyingLine *line ) { - if ( !line->isEmpty() ) - mModified = true; - if ( mLines.count() == 1 ) { - line->clear(); - } else if ( mLines.indexOf( line ) != mLines.count() - 1 ) { - mCurDelLine = line; - slotDeleteLine(); - } + if ( !line->isEmpty() ) + mModified = true; + if ( mLines.count() == 1 ) { + line->clear(); + } else if ( mLines.indexOf( line ) != mLines.count() - 1 ) { + mCurDelLine = line; + slotDeleteLine(); + } } void MultiplyingLineView::slotDeleteLine() { - if ( !mCurDelLine ) - return; + if ( !mCurDelLine ) + return; - MultiplyingLine *line = mCurDelLine; - line->aboutToBeDeleted(); - int pos = mLines.indexOf( line ); - - if ( mCurDelLine->isActive() ) { - int newPos; - if ( pos == 0 ) - newPos = pos + 1; - else - newPos = pos - 1; + MultiplyingLine *line = mCurDelLine; + line->aboutToBeDeleted(); + int pos = mLines.indexOf( line ); + + if ( mCurDelLine->isActive() ) { + int newPos; + if ( pos == 0 ) + newPos = pos + 1; + else + newPos = pos - 1; + + // if there is something left to activate, do so + if ( mLines.at( newPos ) ) + mLines.at( newPos )->activate(); + } - // if there is something left to activate, do so - if ( mLines.at( newPos ) ) - mLines.at( newPos )->activate(); - } - - mLines.removeAll( line ); - line->hide(); - line->setParent( 0 ); - line->deleteLater(); + mLines.removeAll( line ); + line->hide(); + line->setParent( 0 ); + line->deleteLater(); - if( pos > 0 ) - emit lineDeleted( pos ); + if( pos > 0 ) + emit lineDeleted( pos ); - resizeView(); + resizeView(); } void MultiplyingLineView::resizeView() { - if ( mDynamicSizeHint ) { - if ( !mAutoResize ) { - if ( mLines.count() < 6 ) { - setMinimumHeight( mLineHeight * mLines.count() ); - } else { - setMinimumHeight( mLineHeight * 5 ); - setMaximumHeight( mLineHeight * mLines.count() ); - } - } else { - setMinimumHeight( mLineHeight * mLines.count() ); + if ( mDynamicSizeHint ) { + if ( !mAutoResize ) { + if ( mLines.count() < 6 ) { + setMinimumHeight( mLineHeight * mLines.count() ); + } else { + setMinimumHeight( mLineHeight * 5 ); + setMaximumHeight( mLineHeight * mLines.count() ); + } + } else { + setMinimumHeight( mLineHeight * mLines.count() ); + } } - } - parentWidget()->layout()->activate(); - emit sizeHintChanged(); - QTimer::singleShot( 0, this, SLOT(moveCompletionPopup()) ); + parentWidget()->layout()->activate(); + emit sizeHintChanged(); + QTimer::singleShot( 0, this, SLOT(moveCompletionPopup()) ); } void MultiplyingLineView::activateLine( MultiplyingLine *line ) { - line->activate(); - ensureWidgetVisible( line ); + line->activate(); + ensureWidgetVisible( line ); } void MultiplyingLineView::resizeEvent ( QResizeEvent *ev ) { - QScrollArea::resizeEvent(ev); - for( int i = 0; i < mLines.count(); ++i ) { - mLines.at( i )->resize( ev->size().width(), mLineHeight ); - } - ensureVisible( 0, mLines.count() * mLineHeight, 0, 0 ); + QScrollArea::resizeEvent(ev); + for( int i = 0; i < mLines.count(); ++i ) { + mLines.at( i )->resize( ev->size().width(), mLineHeight ); + } + ensureVisible( 0, mLines.count() * mLineHeight, 0, 0 ); } QSize MultiplyingLineView::sizeHint() const { - if ( mDynamicSizeHint ) - return QSize( 200, mLineHeight * mLines.count() ); - else - return QScrollArea::sizeHint(); + if ( mDynamicSizeHint ) + return QSize( 200, mLineHeight * mLines.count() ); + else + return QScrollArea::sizeHint(); } QSize MultiplyingLineView::minimumSizeHint() const { - if ( mDynamicSizeHint ) { - int height; - int numLines = 5; - if ( mLines.count() < numLines ) height = mLineHeight * mLines.count(); - else height = mLineHeight * numLines; - return QSize( 200, height ); - } else - return QScrollArea::minimumSizeHint(); + if ( mDynamicSizeHint ) { + int height; + int numLines = 5; + if ( mLines.count() < numLines ) height = mLineHeight * mLines.count(); + else height = mLineHeight * numLines; + return QSize( 200, height ); + } else + return QScrollArea::minimumSizeHint(); } QList MultiplyingLineView::allData() const { - QList data; + QList data; - QListIterator it( mLines ); - MultiplyingLine *line; - while( it.hasNext()) { - line = it.next(); - if ( !line->data()->isEmpty() ) { - data.append( line->data() ); + QListIterator it( mLines ); + MultiplyingLine *line; + while( it.hasNext()) { + line = it.next(); + if ( !line->data()->isEmpty() ) { + data.append( line->data() ); + } } - } - return data; + return data; } void MultiplyingLineView::setCompletionMode ( KGlobalSettings::Completion mode ) { - if ( mCompletionMode == mode ) - return; - mCompletionMode = mode; - - QListIterator it( mLines ); - while( it.hasNext() ) { - MultiplyingLine *line = it.next(); - line->blockSignals( true ); - line->setCompletionMode( mode ); - line->blockSignals( false ); - } - emit completionModeChanged( mode ); //report change to MultiplyingLineEditor + if ( mCompletionMode == mode ) + return; + mCompletionMode = mode; + + QListIterator it( mLines ); + while( it.hasNext() ) { + MultiplyingLine *line = it.next(); + line->blockSignals( true ); + line->setCompletionMode( mode ); + line->blockSignals( false ); + } + emit completionModeChanged( mode ); //report change to MultiplyingLineEditor } void MultiplyingLineView::removeData( const MultiplyingLineData::Ptr &data ) { // search a line which matches recipient and type - QListIterator it( mLines ); - MultiplyingLine *line = 0; - while (it.hasNext()) { - line = it.next(); - if ( line->data() == data) - break; - } - if ( line ) - line->slotPropagateDeletion(); + QListIterator it( mLines ); + MultiplyingLine *line = 0; + while (it.hasNext()) { + line = it.next(); + if ( line->data() == data) + break; + } + if ( line ) + line->slotPropagateDeletion(); } bool MultiplyingLineView::isModified() const { - if ( mModified ) - return true; + if ( mModified ) + return true; - QListIterator it( mLines ); - MultiplyingLine *line; - while( it.hasNext()) { - line = it.next(); - if ( line->isModified() ) { - return true; + QListIterator it( mLines ); + MultiplyingLine *line; + while( it.hasNext()) { + line = it.next(); + if ( line->isModified() ) { + return true; + } } - } - return false; + return false; } void MultiplyingLineView::clearModified() { - mModified = false; + mModified = false; - QListIterator it( mLines ); - MultiplyingLine *line; - while( it.hasNext() ) { - line = it.next(); - line->clearModified(); - } + QListIterator it( mLines ); + MultiplyingLine *line; + while( it.hasNext() ) { + line = it.next(); + line->clearModified(); + } } void MultiplyingLineView::setFocus() { - if ( !mLines.empty() && mLines.last()->isActive() ) - setFocusBottom(); - else - setFocusTop(); + if ( !mLines.empty() && mLines.last()->isActive() ) + setFocusBottom(); + else + setFocusTop(); } void MultiplyingLineView::setFocusTop() { - if ( !mLines.empty() ) { - MultiplyingLine *line = mLines.first(); - if ( line ) - line->activate(); + if ( !mLines.empty() ) { + MultiplyingLine *line = mLines.first(); + if ( line ) + line->activate(); + else + kWarning() <<"No first"; + } else - kWarning() <<"No first"; - } - else - kWarning() <<"No first"; + kWarning() <<"No first"; } void MultiplyingLineView::setFocusBottom() { - MultiplyingLine *line = mLines.last(); - if ( line ) { - ensureWidgetVisible( line ); - line->activate(); - } - else - kWarning() <<"No last"; + MultiplyingLine *line = mLines.last(); + if ( line ) { + ensureWidgetVisible( line ); + line->activate(); + } + else + kWarning() <<"No last"; } int MultiplyingLineView::setFirstColumnWidth( int w ) { - mFirstColumnWidth = w; + mFirstColumnWidth = w; - QListIterator it( mLines ); - MultiplyingLine *line; - while(it.hasNext()) { - line = it.next(); - mFirstColumnWidth = line->setColumnWidth( mFirstColumnWidth ); - } + QListIterator it( mLines ); + MultiplyingLine *line; + while(it.hasNext()) { + line = it.next(); + mFirstColumnWidth = line->setColumnWidth( mFirstColumnWidth ); + } - resizeView(); - return mFirstColumnWidth; + resizeView(); + return mFirstColumnWidth; } void MultiplyingLineView::moveCompletionPopup() { - foreach ( MultiplyingLine *const line, mLines ) - line->moveCompletionPopup(); + foreach ( MultiplyingLine *const line, mLines ) + line->moveCompletionPopup(); } QList< MultiplyingLine* > MultiplyingLineView::lines() const { - return mLines; + return mLines; } void MultiplyingLineView::setAutoResize( bool resize ) { - mAutoResize = resize; + mAutoResize = resize; - if ( mAutoResize ) { - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setMaximumHeight( QWIDGETSIZE_MAX ); - } else { - setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); - setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - } + if ( mAutoResize ) { + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setMaximumHeight( QWIDGETSIZE_MAX ); + } else { + setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + } } bool MultiplyingLineView::autoResize() { - return mAutoResize; + return mAutoResize; } void MultiplyingLineView::setDynamicSizeHint( bool dynamic ) { - mDynamicSizeHint = dynamic; + mDynamicSizeHint = dynamic; } bool MultiplyingLineView::dynamicSizeHint() const { - return mDynamicSizeHint; + return mDynamicSizeHint; } diff -Nru kdepim-4.12.97/libkdepim/multiplyingline/multiplyinglineview_p.h kdepim-4.13.0/libkdepim/multiplyingline/multiplyinglineview_p.h --- kdepim-4.12.97/libkdepim/multiplyingline/multiplyinglineview_p.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/multiplyingline/multiplyinglineview_p.h 2014-04-10 07:40:20.000000000 +0000 @@ -34,11 +34,11 @@ #include namespace KPIM { - + class MultiplyingLineView : public QScrollArea { Q_OBJECT - public: +public: MultiplyingLineView( MultiplyingLineFactory* factory, MultiplyingLineEditor *parent ); ~MultiplyingLineView(){} @@ -66,7 +66,7 @@ */ void clearModified(); - /** Activates the line */ + /** Activates the line */ void activateLine( MultiplyingLine *line ); /**QScrollArea @@ -93,7 +93,7 @@ QList lines() const; - public slots: +public slots: void setCompletionMode( KGlobalSettings::Completion mode ); MultiplyingLine *addLine(); @@ -101,7 +101,7 @@ void setFocusTop(); void setFocusBottom(); - signals: +signals: void focusUp(); void focusDown(); void focusRight(); @@ -110,11 +110,11 @@ void lineDeleted( int pos ); void lineAdded( KPIM::MultiplyingLine * ); - protected: +protected: void resizeEvent( QResizeEvent * ); void resizeView(); - protected slots: +protected slots: void slotReturnPressed( KPIM::MultiplyingLine * ); void slotDownPressed( KPIM::MultiplyingLine * ); void slotUpPressed( KPIM::MultiplyingLine * ); @@ -123,7 +123,7 @@ void moveCompletionPopup(); void moveScrollBarToEnd(); - private: +private: QList mLines; QPointer mCurDelLine; int mLineHeight; diff -Nru kdepim-4.12.97/libkdepim/prefs/kprefsdialog.cpp kdepim-4.13.0/libkdepim/prefs/kprefsdialog.cpp --- kdepim-4.12.97/libkdepim/prefs/kprefsdialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/prefs/kprefsdialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -57,157 +57,157 @@ namespace KPrefsWidFactory { KPrefsWid *create( KConfigSkeletonItem *item, QWidget *parent ) { - KConfigSkeleton::ItemBool *boolItem = - dynamic_cast( item ); - if ( boolItem ) { - return new KPrefsWidBool( boolItem, parent ); - } - - KConfigSkeleton::ItemString *stringItem = - dynamic_cast( item ); - if ( stringItem ) { - return new KPrefsWidString( stringItem, parent ); - } - - KConfigSkeleton::ItemEnum *enumItem = - dynamic_cast( item ); - if ( enumItem ) { - QList choices = enumItem->choices(); - if ( choices.isEmpty() ) { - kError() << "Enum has no choices."; - return 0; - } else { - KPrefsWidRadios *radios = new KPrefsWidRadios( enumItem, parent ); - QList::ConstIterator it; - int value = 0; - QList::ConstIterator end(choices.constEnd()); - for ( it = choices.constBegin(); it != end; ++it ) { - radios->addRadio( value++, (*it).label ); - } - return radios; - } - } - - KConfigSkeleton::ItemInt *intItem = dynamic_cast( item ); - if ( intItem ) { - return new KPrefsWidInt( intItem, parent ); - } + KConfigSkeleton::ItemBool *boolItem = + dynamic_cast( item ); + if ( boolItem ) { + return new KPrefsWidBool( boolItem, parent ); + } + + KConfigSkeleton::ItemString *stringItem = + dynamic_cast( item ); + if ( stringItem ) { + return new KPrefsWidString( stringItem, parent ); + } + + KConfigSkeleton::ItemEnum *enumItem = + dynamic_cast( item ); + if ( enumItem ) { + QList choices = enumItem->choices(); + if ( choices.isEmpty() ) { + kError() << "Enum has no choices."; + return 0; + } else { + KPrefsWidRadios *radios = new KPrefsWidRadios( enumItem, parent ); + QList::ConstIterator it; + int value = 0; + QList::ConstIterator end(choices.constEnd()); + for ( it = choices.constBegin(); it != end; ++it ) { + radios->addRadio( value++, (*it).label ); + } + return radios; + } + } + + KConfigSkeleton::ItemInt *intItem = dynamic_cast( item ); + if ( intItem ) { + return new KPrefsWidInt( intItem, parent ); + } - return 0; + return 0; } } // namespace KPrefsWidFactory QList KPrefsWid::widgets() const { - return QList(); + return QList(); } KPrefsWidBool::KPrefsWidBool( KConfigSkeleton::ItemBool *item, QWidget *parent ) - : mItem( item ) + : mItem( item ) { - mCheck = new QCheckBox( mItem->label(), parent ); - connect( mCheck, SIGNAL(clicked()), SIGNAL(changed()) ); - QString toolTip = mItem->toolTip(); - if ( !toolTip.isEmpty() ) { - mCheck->setToolTip( toolTip ); - } - QString whatsThis = mItem->whatsThis(); - if ( !whatsThis.isEmpty() ) { - mCheck->setWhatsThis( whatsThis ); - } + mCheck = new QCheckBox( mItem->label(), parent ); + connect( mCheck, SIGNAL(clicked()), SIGNAL(changed()) ); + QString toolTip = mItem->toolTip(); + if ( !toolTip.isEmpty() ) { + mCheck->setToolTip( toolTip ); + } + QString whatsThis = mItem->whatsThis(); + if ( !whatsThis.isEmpty() ) { + mCheck->setWhatsThis( whatsThis ); + } } void KPrefsWidBool::readConfig() { - mCheck->setChecked( mItem->value() ); + mCheck->setChecked( mItem->value() ); } void KPrefsWidBool::writeConfig() { - mItem->setValue( mCheck->isChecked() ); + mItem->setValue( mCheck->isChecked() ); } QCheckBox *KPrefsWidBool::checkBox() { - return mCheck; + return mCheck; } QList KPrefsWidBool::widgets() const { - QList widgets; - widgets.append( mCheck ); - return widgets; + QList widgets; + widgets.append( mCheck ); + return widgets; } KPrefsWidInt::KPrefsWidInt( KConfigSkeleton::ItemInt *item, QWidget *parent ) - : mItem( item ) + : mItem( item ) { - mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); - mSpin = new QSpinBox( parent ); - if ( !mItem->minValue().isNull() ) { - mSpin->setMinimum( mItem->minValue().toInt() ); - } - if ( !mItem->maxValue().isNull() ) { - mSpin->setMaximum( mItem->maxValue().toInt() ); - } - connect( mSpin, SIGNAL(valueChanged(int)), SIGNAL(changed()) ); - mLabel->setBuddy( mSpin ); - QString toolTip = mItem->toolTip(); - if ( !toolTip.isEmpty() ) { - mLabel->setToolTip( toolTip ); - mSpin->setToolTip( toolTip ); - } - QString whatsThis = mItem->whatsThis(); - if ( !whatsThis.isEmpty() ) { - mLabel->setWhatsThis( whatsThis ); - mSpin->setWhatsThis( whatsThis ); - } + mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); + mSpin = new QSpinBox( parent ); + if ( !mItem->minValue().isNull() ) { + mSpin->setMinimum( mItem->minValue().toInt() ); + } + if ( !mItem->maxValue().isNull() ) { + mSpin->setMaximum( mItem->maxValue().toInt() ); + } + connect( mSpin, SIGNAL(valueChanged(int)), SIGNAL(changed()) ); + mLabel->setBuddy( mSpin ); + QString toolTip = mItem->toolTip(); + if ( !toolTip.isEmpty() ) { + mLabel->setToolTip( toolTip ); + mSpin->setToolTip( toolTip ); + } + QString whatsThis = mItem->whatsThis(); + if ( !whatsThis.isEmpty() ) { + mLabel->setWhatsThis( whatsThis ); + mSpin->setWhatsThis( whatsThis ); + } } void KPrefsWidInt::readConfig() { - mSpin->setValue( mItem->value() ); + mSpin->setValue( mItem->value() ); } void KPrefsWidInt::writeConfig() { - mItem->setValue( mSpin->value() ); + mItem->setValue( mSpin->value() ); } QLabel *KPrefsWidInt::label() { - return mLabel; + return mLabel; } QSpinBox *KPrefsWidInt::spinBox() { - return mSpin; + return mSpin; } QList KPrefsWidInt::widgets() const { - QList widgets; - widgets.append( mLabel ); - widgets.append( mSpin ); - return widgets; + QList widgets; + widgets.append( mLabel ); + widgets.append( mSpin ); + return widgets; } KPrefsWidColor::KPrefsWidColor( KConfigSkeleton::ItemColor *item, QWidget *parent ) - : mItem( item ) + : mItem( item ) { - mButton = new KColorButton( parent ); - connect( mButton, SIGNAL(changed(QColor)), SIGNAL(changed()) ); - mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); - mLabel->setBuddy( mButton ); - QString toolTip = mItem->toolTip(); - if ( !toolTip.isEmpty() ) { - mButton->setToolTip( toolTip ); - } - QString whatsThis = mItem->whatsThis(); - if ( !whatsThis.isEmpty() ) { - mButton->setWhatsThis( whatsThis ); - } + mButton = new KColorButton( parent ); + connect( mButton, SIGNAL(changed(QColor)), SIGNAL(changed()) ); + mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); + mLabel->setBuddy( mButton ); + QString toolTip = mItem->toolTip(); + if ( !toolTip.isEmpty() ) { + mButton->setToolTip( toolTip ); + } + QString whatsThis = mItem->whatsThis(); + if ( !whatsThis.isEmpty() ) { + mButton->setWhatsThis( whatsThis ); + } } KPrefsWidColor::~KPrefsWidColor() @@ -216,45 +216,45 @@ void KPrefsWidColor::readConfig() { - mButton->setColor( mItem->value() ); + mButton->setColor( mItem->value() ); } void KPrefsWidColor::writeConfig() { - mItem->setValue( mButton->color() ); + mItem->setValue( mButton->color() ); } QLabel *KPrefsWidColor::label() { - return mLabel; + return mLabel; } KColorButton *KPrefsWidColor::button() { - return mButton; + return mButton; } KPrefsWidFont::KPrefsWidFont( KConfigSkeleton::ItemFont *item, QWidget *parent, const QString &sampleText ) - : mItem( item ) + : mItem( item ) { - mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); + mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); - mPreview = new QLabel( sampleText, parent ); - mPreview->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); + mPreview = new QLabel( sampleText, parent ); + mPreview->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); - mButton = new QPushButton( i18n( "Choose..." ), parent ); - connect( mButton, SIGNAL(clicked()), SLOT(selectFont()) ); - QString toolTip = mItem->toolTip(); - if ( !toolTip.isEmpty() ) { - mPreview->setToolTip( toolTip ); - mButton->setToolTip( toolTip ); - } - QString whatsThis = mItem->whatsThis(); - if ( !whatsThis.isEmpty() ) { - mPreview->setWhatsThis( whatsThis ); - mButton->setWhatsThis( whatsThis ); - } + mButton = new QPushButton( i18n( "Choose..." ), parent ); + connect( mButton, SIGNAL(clicked()), SLOT(selectFont()) ); + QString toolTip = mItem->toolTip(); + if ( !toolTip.isEmpty() ) { + mPreview->setToolTip( toolTip ); + mButton->setToolTip( toolTip ); + } + QString whatsThis = mItem->whatsThis(); + if ( !whatsThis.isEmpty() ) { + mPreview->setWhatsThis( whatsThis ); + mButton->setWhatsThis( whatsThis ); + } } KPrefsWidFont::~KPrefsWidFont() @@ -263,183 +263,183 @@ void KPrefsWidFont::readConfig() { - mPreview->setFont( mItem->value() ); + mPreview->setFont( mItem->value() ); } void KPrefsWidFont::writeConfig() { - mItem->setValue( mPreview->font() ); + mItem->setValue( mPreview->font() ); } QLabel *KPrefsWidFont::label() { - return mLabel; + return mLabel; } QFrame *KPrefsWidFont::preview() { - return mPreview; + return mPreview; } QPushButton *KPrefsWidFont::button() { - return mButton; + return mButton; } void KPrefsWidFont::selectFont() { #ifndef QT_NO_FONTDIALOG - QFont myFont( mPreview->font() ); - int result = KFontDialog::getFont( myFont ); - if ( result == KFontDialog::Accepted ) { - mPreview->setFont( myFont ); - emit changed(); - } + QFont myFont( mPreview->font() ); + int result = KFontDialog::getFont( myFont ); + if ( result == KFontDialog::Accepted ) { + mPreview->setFont( myFont ); + emit changed(); + } #endif } KPrefsWidTime::KPrefsWidTime( KConfigSkeleton::ItemDateTime *item, QWidget *parent ) - : mItem( item ) + : mItem( item ) { - mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); - mTimeEdit = new KTimeComboBox( parent ); - mLabel->setBuddy( mTimeEdit ); - connect( mTimeEdit, SIGNAL(timeEdited(QTime)), SIGNAL(changed()) ); - connect( mTimeEdit, SIGNAL(timeEntered(QTime)), SIGNAL(changed()) ); - QString toolTip = mItem->toolTip(); - if ( !toolTip.isEmpty() ) { - mTimeEdit->setToolTip( toolTip ); - } - QString whatsThis = mItem->whatsThis(); - if ( !whatsThis.isEmpty() ) { - mTimeEdit->setWhatsThis( whatsThis ); - } + mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); + mTimeEdit = new KTimeComboBox( parent ); + mLabel->setBuddy( mTimeEdit ); + connect( mTimeEdit, SIGNAL(timeEdited(QTime)), SIGNAL(changed()) ); + connect( mTimeEdit, SIGNAL(timeEntered(QTime)), SIGNAL(changed()) ); + QString toolTip = mItem->toolTip(); + if ( !toolTip.isEmpty() ) { + mTimeEdit->setToolTip( toolTip ); + } + QString whatsThis = mItem->whatsThis(); + if ( !whatsThis.isEmpty() ) { + mTimeEdit->setWhatsThis( whatsThis ); + } } void KPrefsWidTime::readConfig() { - mTimeEdit->setTime( mItem->value().time() ); + mTimeEdit->setTime( mItem->value().time() ); } void KPrefsWidTime::writeConfig() { - // Don't overwrite the date value of the QDateTime, so we can use a - // KPrefsWidTime and a KPrefsWidDate on the same config entry! - QDateTime dt( mItem->value() ); - dt.setTime( mTimeEdit->time() ); - mItem->setValue( dt ); + // Don't overwrite the date value of the QDateTime, so we can use a + // KPrefsWidTime and a KPrefsWidDate on the same config entry! + QDateTime dt( mItem->value() ); + dt.setTime( mTimeEdit->time() ); + mItem->setValue( dt ); } QLabel *KPrefsWidTime::label() { - return mLabel; + return mLabel; } KTimeComboBox *KPrefsWidTime::timeEdit() { - return mTimeEdit; + return mTimeEdit; } KPrefsWidDuration::KPrefsWidDuration( KConfigSkeleton::ItemDateTime *item, const QString &format, QWidget *parent ) - : mItem( item ) + : mItem( item ) { - mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); - mTimeEdit = new QTimeEdit( parent ); - mLabel->setBuddy( mTimeEdit ); - if ( format.isEmpty() ) { - mTimeEdit->setDisplayFormat( QLatin1String( "hh:mm:ss" ) ); - } else { - mTimeEdit->setDisplayFormat( format ); - } - mTimeEdit->setMinimumTime( QTime( 0, 1 ) ); // [1 min] - mTimeEdit->setMaximumTime( QTime( 24, 0 ) ); // [24 hr] - connect( mTimeEdit, SIGNAL(timeChanged(QTime)), SIGNAL(changed()) ); - QString toolTip = mItem->toolTip(); - if ( !toolTip.isEmpty() ) { - mTimeEdit->setToolTip( toolTip ); - } - QString whatsThis = mItem->whatsThis(); - if ( !whatsThis.isEmpty() ) { - mTimeEdit->setWhatsThis( whatsThis ); - } + mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); + mTimeEdit = new QTimeEdit( parent ); + mLabel->setBuddy( mTimeEdit ); + if ( format.isEmpty() ) { + mTimeEdit->setDisplayFormat( QLatin1String( "hh:mm:ss" ) ); + } else { + mTimeEdit->setDisplayFormat( format ); + } + mTimeEdit->setMinimumTime( QTime( 0, 1 ) ); // [1 min] + mTimeEdit->setMaximumTime( QTime( 24, 0 ) ); // [24 hr] + connect( mTimeEdit, SIGNAL(timeChanged(QTime)), SIGNAL(changed()) ); + QString toolTip = mItem->toolTip(); + if ( !toolTip.isEmpty() ) { + mTimeEdit->setToolTip( toolTip ); + } + QString whatsThis = mItem->whatsThis(); + if ( !whatsThis.isEmpty() ) { + mTimeEdit->setWhatsThis( whatsThis ); + } } void KPrefsWidDuration::readConfig() { - mTimeEdit->setTime( mItem->value().time() ); + mTimeEdit->setTime( mItem->value().time() ); } void KPrefsWidDuration::writeConfig() { - QDateTime dt( mItem->value() ); - dt.setTime( mTimeEdit->time() ); - mItem->setValue( dt ); + QDateTime dt( mItem->value() ); + dt.setTime( mTimeEdit->time() ); + mItem->setValue( dt ); } QLabel *KPrefsWidDuration::label() { - return mLabel; + return mLabel; } QTimeEdit *KPrefsWidDuration::timeEdit() { - return mTimeEdit; + return mTimeEdit; } KPrefsWidDate::KPrefsWidDate( KConfigSkeleton::ItemDateTime *item, QWidget *parent ) - : mItem( item ) + : mItem( item ) { - mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); - mDateEdit = new KDateComboBox( parent ); - mLabel->setBuddy( mDateEdit ); - connect( mDateEdit, SIGNAL(dateEdited(QDate)), SIGNAL(changed()) ); - QString toolTip = mItem->toolTip(); - if ( !toolTip.isEmpty() ) { - mDateEdit->setToolTip( toolTip ); - } - QString whatsThis = mItem->whatsThis(); - if ( !whatsThis.isEmpty() ) { - mDateEdit->setWhatsThis( whatsThis ); - } + mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); + mDateEdit = new KDateComboBox( parent ); + mLabel->setBuddy( mDateEdit ); + connect( mDateEdit, SIGNAL(dateEdited(QDate)), SIGNAL(changed()) ); + QString toolTip = mItem->toolTip(); + if ( !toolTip.isEmpty() ) { + mDateEdit->setToolTip( toolTip ); + } + QString whatsThis = mItem->whatsThis(); + if ( !whatsThis.isEmpty() ) { + mDateEdit->setWhatsThis( whatsThis ); + } } void KPrefsWidDate::readConfig() { - if ( !mItem->value().date().isValid() ) { - mItem->setValue( QDateTime::currentDateTime() ); - } - mDateEdit->setDate( mItem->value().date().isValid() ? - mItem->value().date() : QDate::currentDate() ); + if ( !mItem->value().date().isValid() ) { + mItem->setValue( QDateTime::currentDateTime() ); + } + mDateEdit->setDate( mItem->value().date().isValid() ? + mItem->value().date() : QDate::currentDate() ); } void KPrefsWidDate::writeConfig() { - QDateTime dt( mItem->value() ); - dt.setDate( mDateEdit->date() ); - mItem->setValue( dt ); - if ( !mItem->value().date().isValid() ) { - mItem->setValue( QDateTime::currentDateTime() ); - } + QDateTime dt( mItem->value() ); + dt.setDate( mDateEdit->date() ); + mItem->setValue( dt ); + if ( !mItem->value().date().isValid() ) { + mItem->setValue( QDateTime::currentDateTime() ); + } } QLabel *KPrefsWidDate::label() { - return mLabel; + return mLabel; } KDateComboBox *KPrefsWidDate::dateEdit() { - return mDateEdit; + return mDateEdit; } KPrefsWidRadios::KPrefsWidRadios( KConfigSkeleton::ItemEnum *item, QWidget *parent ) - : mItem( item ) + : mItem( item ) { - mBox = new QGroupBox( mItem->label(), parent ); - new QVBoxLayout( mBox ); - mGroup = new QButtonGroup( parent ); - connect( mGroup, SIGNAL(buttonClicked(int)), SIGNAL(changed()) ); + mBox = new QGroupBox( mItem->label(), parent ); + new QVBoxLayout( mBox ); + mGroup = new QButtonGroup( parent ); + connect( mGroup, SIGNAL(buttonClicked(int)), SIGNAL(changed()) ); } KPrefsWidRadios::~KPrefsWidRadios() @@ -449,48 +449,48 @@ void KPrefsWidRadios::addRadio( int value, const QString &text, const QString &toolTip, const QString &whatsThis ) { - QRadioButton *r = new QRadioButton( text, mBox ); - mBox->layout()->addWidget( r ); - mGroup->addButton( r, value ); - if ( !toolTip.isEmpty() ) { - r->setToolTip( toolTip ); - } - if ( !whatsThis.isEmpty() ) { - r->setWhatsThis( whatsThis ); - } + QRadioButton *r = new QRadioButton( text, mBox ); + mBox->layout()->addWidget( r ); + mGroup->addButton( r, value ); + if ( !toolTip.isEmpty() ) { + r->setToolTip( toolTip ); + } + if ( !whatsThis.isEmpty() ) { + r->setWhatsThis( whatsThis ); + } } QGroupBox *KPrefsWidRadios::groupBox() const { - return mBox; + return mBox; } void KPrefsWidRadios::readConfig() { - if ( !mGroup->button( mItem->value() ) ) - return; - mGroup->button( mItem->value() )->setChecked( true ); + if ( !mGroup->button( mItem->value() ) ) + return; + mGroup->button( mItem->value() )->setChecked( true ); } void KPrefsWidRadios::writeConfig() { - mItem->setValue( mGroup->checkedId() ); + mItem->setValue( mGroup->checkedId() ); } QList KPrefsWidRadios::widgets() const { - QList w; - w.append( mBox ); - return w; + QList w; + w.append( mBox ); + return w; } KPrefsWidCombo::KPrefsWidCombo( KConfigSkeleton::ItemEnum *item, QWidget *parent ) - : mItem( item ) + : mItem( item ) { - KHBox *hbox = new KHBox( parent ); - new QLabel( mItem->label(), hbox ); - mCombo = new KComboBox( hbox ); - connect( mCombo, SIGNAL(activated(int)), SIGNAL(changed()) ); + KHBox *hbox = new KHBox( parent ); + new QLabel( mItem->label(), hbox ); + mCombo = new KComboBox( hbox ); + connect( mCombo, SIGNAL(activated(int)), SIGNAL(changed()) ); } KPrefsWidCombo::~KPrefsWidCombo() @@ -499,43 +499,43 @@ void KPrefsWidCombo::readConfig() { - mCombo->setCurrentIndex( mItem->value() ); + mCombo->setCurrentIndex( mItem->value() ); } void KPrefsWidCombo::writeConfig() { - mItem->setValue( mCombo->currentIndex() ); + mItem->setValue( mCombo->currentIndex() ); } QList KPrefsWidCombo::widgets() const { - QList w; - w.append( mCombo ); - return w; + QList w; + w.append( mCombo ); + return w; } KComboBox *KPrefsWidCombo::comboBox() { - return mCombo; + return mCombo; } KPrefsWidString::KPrefsWidString( KConfigSkeleton::ItemString *item, QWidget *parent, KLineEdit::EchoMode echomode ) - : mItem( item ) + : mItem( item ) { - mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); - mEdit = new KLineEdit( parent ); - mLabel->setBuddy( mEdit ); - connect( mEdit, SIGNAL(textChanged(QString)), SIGNAL(changed()) ); - mEdit->setEchoMode( echomode ); - QString toolTip = mItem->toolTip(); - if ( !toolTip.isEmpty() ) { - mEdit->setToolTip( toolTip ); - } - QString whatsThis = mItem->whatsThis(); - if ( !whatsThis.isEmpty() ) { - mEdit->setWhatsThis( whatsThis ); - } + mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); + mEdit = new KLineEdit( parent ); + mLabel->setBuddy( mEdit ); + connect( mEdit, SIGNAL(textChanged(QString)), SIGNAL(changed()) ); + mEdit->setEchoMode( echomode ); + QString toolTip = mItem->toolTip(); + if ( !toolTip.isEmpty() ) { + mEdit->setToolTip( toolTip ); + } + QString whatsThis = mItem->whatsThis(); + if ( !whatsThis.isEmpty() ) { + mEdit->setWhatsThis( whatsThis ); + } } KPrefsWidString::~KPrefsWidString() @@ -544,50 +544,50 @@ void KPrefsWidString::readConfig() { - mEdit->setText( mItem->value() ); + mEdit->setText( mItem->value() ); } void KPrefsWidString::writeConfig() { - mItem->setValue( mEdit->text() ); + mItem->setValue( mEdit->text() ); } QLabel *KPrefsWidString::label() { - return mLabel; + return mLabel; } KLineEdit *KPrefsWidString::lineEdit() { - return mEdit; + return mEdit; } QList KPrefsWidString::widgets() const { - QList widgets; - widgets.append( mLabel ); - widgets.append( mEdit ); - return widgets; + QList widgets; + widgets.append( mLabel ); + widgets.append( mEdit ); + return widgets; } KPrefsWidPath::KPrefsWidPath( KConfigSkeleton::ItemPath *item, QWidget *parent, const QString &filter, KFile::Modes mode ) - : mItem( item ) + : mItem( item ) { - mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); - mURLRequester = new KUrlRequester( parent ); - mLabel->setBuddy( mURLRequester ); - mURLRequester->setMode( mode ); - mURLRequester->setFilter( filter ); - connect( mURLRequester, SIGNAL(textChanged(QString)), SIGNAL(changed()) ); - QString toolTip = mItem->toolTip(); - if ( !toolTip.isEmpty() ) { - mURLRequester->setToolTip( toolTip ); - } - QString whatsThis = mItem->whatsThis(); - if ( !whatsThis.isEmpty() ) { - mURLRequester->setWhatsThis( whatsThis ); - } + mLabel = new QLabel( mItem->label() + QLatin1Char( ':' ), parent ); + mURLRequester = new KUrlRequester( parent ); + mLabel->setBuddy( mURLRequester ); + mURLRequester->setMode( mode ); + mURLRequester->setFilter( filter ); + connect( mURLRequester, SIGNAL(textChanged(QString)), SIGNAL(changed()) ); + QString toolTip = mItem->toolTip(); + if ( !toolTip.isEmpty() ) { + mURLRequester->setToolTip( toolTip ); + } + QString whatsThis = mItem->whatsThis(); + if ( !whatsThis.isEmpty() ) { + mURLRequester->setWhatsThis( whatsThis ); + } } KPrefsWidPath::~KPrefsWidPath() @@ -596,124 +596,124 @@ void KPrefsWidPath::readConfig() { - mURLRequester->setUrl( KUrl( mItem->value() ) ); + mURLRequester->setUrl( KUrl( mItem->value() ) ); } void KPrefsWidPath::writeConfig() { - mItem->setValue( mURLRequester->url().path() ); + mItem->setValue( mURLRequester->url().path() ); } QLabel *KPrefsWidPath::label() { - return mLabel; + return mLabel; } KUrlRequester *KPrefsWidPath::urlRequester() { - return mURLRequester; + return mURLRequester; } QList KPrefsWidPath::widgets() const { - QList widgets; - widgets.append( mLabel ); - widgets.append( mURLRequester ); - return widgets; + QList widgets; + widgets.append( mLabel ); + widgets.append( mURLRequester ); + return widgets; } KPrefsWidManager::KPrefsWidManager( KConfigSkeleton *prefs ) - : mPrefs( prefs ) + : mPrefs( prefs ) { } KPrefsWidManager::~KPrefsWidManager() { - qDeleteAll( mPrefsWids ); - mPrefsWids.clear(); + qDeleteAll( mPrefsWids ); + mPrefsWids.clear(); } void KPrefsWidManager::addWid( KPrefsWid *wid ) { - mPrefsWids.append( wid ); + mPrefsWids.append( wid ); } KPrefsWidBool *KPrefsWidManager::addWidBool( KConfigSkeleton::ItemBool *item, QWidget *parent ) { - KPrefsWidBool *w = new KPrefsWidBool( item, parent ); - addWid( w ); - return w; + KPrefsWidBool *w = new KPrefsWidBool( item, parent ); + addWid( w ); + return w; } KPrefsWidTime *KPrefsWidManager::addWidTime( KConfigSkeleton::ItemDateTime *item, QWidget *parent ) { - KPrefsWidTime *w = new KPrefsWidTime( item, parent ); - addWid( w ); - return w; + KPrefsWidTime *w = new KPrefsWidTime( item, parent ); + addWid( w ); + return w; } KPrefsWidDuration *KPrefsWidManager::addWidDuration( KConfigSkeleton::ItemDateTime *item, const QString &format, QWidget *parent ) { - KPrefsWidDuration *w = new KPrefsWidDuration( item, format, parent ); - addWid( w ); - return w; + KPrefsWidDuration *w = new KPrefsWidDuration( item, format, parent ); + addWid( w ); + return w; } KPrefsWidDate *KPrefsWidManager::addWidDate( KConfigSkeleton::ItemDateTime *item, QWidget *parent ) { - KPrefsWidDate *w = new KPrefsWidDate( item, parent ); - addWid( w ); - return w; + KPrefsWidDate *w = new KPrefsWidDate( item, parent ); + addWid( w ); + return w; } KPrefsWidColor *KPrefsWidManager::addWidColor( KConfigSkeleton::ItemColor *item, QWidget *parent ) { - KPrefsWidColor *w = new KPrefsWidColor( item, parent ); - addWid( w ); - return w; + KPrefsWidColor *w = new KPrefsWidColor( item, parent ); + addWid( w ); + return w; } KPrefsWidRadios *KPrefsWidManager::addWidRadios( KConfigSkeleton::ItemEnum *item, QWidget *parent ) { - KPrefsWidRadios *w = new KPrefsWidRadios( item, parent ); - QList choices; - choices = item->choices2(); - QList::ConstIterator it; - int value = 0; - for ( it = choices.constBegin(); it != choices.constEnd(); ++it ) { - w->addRadio( value++, (*it).label, (*it).toolTip, (*it).whatsThis ); - } - addWid( w ); - return w; + KPrefsWidRadios *w = new KPrefsWidRadios( item, parent ); + QList choices; + choices = item->choices2(); + QList::ConstIterator it; + int value = 0; + for ( it = choices.constBegin(); it != choices.constEnd(); ++it ) { + w->addRadio( value++, (*it).label, (*it).toolTip, (*it).whatsThis ); + } + addWid( w ); + return w; } KPrefsWidCombo *KPrefsWidManager::addWidCombo( KConfigSkeleton::ItemEnum *item, QWidget *parent ) { - KPrefsWidCombo *w = new KPrefsWidCombo( item, parent ); - QList choices; - choices = item->choices(); - QList::ConstIterator it; - for ( it = choices.constBegin(); it != choices.constEnd(); ++it ) { - w->comboBox()->addItem( (*it).label ); - } - addWid( w ); - return w; + KPrefsWidCombo *w = new KPrefsWidCombo( item, parent ); + QList choices; + choices = item->choices(); + QList::ConstIterator it; + for ( it = choices.constBegin(); it != choices.constEnd(); ++it ) { + w->comboBox()->addItem( (*it).label ); + } + addWid( w ); + return w; } KPrefsWidString *KPrefsWidManager::addWidString( KConfigSkeleton::ItemString *item, QWidget *parent ) { - KPrefsWidString *w = new KPrefsWidString( item, parent, KLineEdit::Normal ); - addWid( w ); - return w; + KPrefsWidString *w = new KPrefsWidString( item, parent, KLineEdit::Normal ); + addWid( w ); + return w; } KPrefsWidPath *KPrefsWidManager::addWidPath( KConfigSkeleton::ItemPath *item, @@ -721,75 +721,75 @@ const QString &filter, KFile::Modes mode ) { - KPrefsWidPath *w = new KPrefsWidPath( item, parent, filter, mode ); - addWid( w ); - return w; + KPrefsWidPath *w = new KPrefsWidPath( item, parent, filter, mode ); + addWid( w ); + return w; } KPrefsWidString *KPrefsWidManager::addWidPassword( KConfigSkeleton::ItemString *item, QWidget *parent ) { - KPrefsWidString *w = new KPrefsWidString( item, parent, KLineEdit::Password ); - addWid( w ); - return w; + KPrefsWidString *w = new KPrefsWidString( item, parent, KLineEdit::Password ); + addWid( w ); + return w; } KPrefsWidFont *KPrefsWidManager::addWidFont( KConfigSkeleton::ItemFont *item, QWidget *parent, const QString &sampleText ) { - KPrefsWidFont *w = new KPrefsWidFont( item, parent, sampleText ); - addWid( w ); - return w; + KPrefsWidFont *w = new KPrefsWidFont( item, parent, sampleText ); + addWid( w ); + return w; } KPrefsWidInt *KPrefsWidManager::addWidInt( KConfigSkeleton::ItemInt *item, QWidget *parent ) { - KPrefsWidInt *w = new KPrefsWidInt( item, parent ); - addWid( w ); - return w; + KPrefsWidInt *w = new KPrefsWidInt( item, parent ); + addWid( w ); + return w; } void KPrefsWidManager::setWidDefaults() { - bool tmp = mPrefs->useDefaults( true ); - readWidConfig(); - mPrefs->useDefaults( tmp ); + bool tmp = mPrefs->useDefaults( true ); + readWidConfig(); + mPrefs->useDefaults( tmp ); } void KPrefsWidManager::readWidConfig() { - QList::Iterator it; - for ( it = mPrefsWids.begin(); it != mPrefsWids.end(); ++it ) { - (*it)->readConfig(); - } + QList::Iterator it; + for ( it = mPrefsWids.begin(); it != mPrefsWids.end(); ++it ) { + (*it)->readConfig(); + } } void KPrefsWidManager::writeWidConfig() { - QList::Iterator it; - for ( it = mPrefsWids.begin(); it != mPrefsWids.end(); ++it ) { - (*it)->writeConfig(); - } + QList::Iterator it; + for ( it = mPrefsWids.begin(); it != mPrefsWids.end(); ++it ) { + (*it)->writeConfig(); + } - mPrefs->writeConfig(); + mPrefs->writeConfig(); } KPrefsDialog::KPrefsDialog( KConfigSkeleton *prefs, QWidget *parent, bool modal ) - : KPageDialog( parent ), - KPrefsWidManager( prefs ) + : KPageDialog( parent ), + KPrefsWidManager( prefs ) { - setFaceType( List ); - setCaption( i18n( "Preferences" ) ); - setButtons( Ok|Apply|Cancel|Default ); - setDefaultButton( Ok ); - setModal( modal ); - showButtonSeparator( true ); - connect( this, SIGNAL(okClicked()), SLOT(slotOk()) ); - connect( this, SIGNAL(applyClicked()), SLOT(slotApply()) ); - connect( this, SIGNAL(defaultClicked()), SLOT(slotDefault()) ); - connect( this, SIGNAL(cancelClicked()), SLOT(reject()) ); + setFaceType( List ); + setCaption( i18n( "Preferences" ) ); + setButtons( Ok|Apply|Cancel|Default ); + setDefaultButton( Ok ); + setModal( modal ); + showButtonSeparator( true ); + connect( this, SIGNAL(okClicked()), SLOT(slotOk()) ); + connect( this, SIGNAL(applyClicked()), SLOT(slotApply()) ); + connect( this, SIGNAL(defaultClicked()), SLOT(slotDefault()) ); + connect( this, SIGNAL(cancelClicked()), SLOT(reject()) ); } KPrefsDialog::~KPrefsDialog() @@ -799,140 +799,140 @@ void KPrefsDialog::autoCreate() { - KConfigSkeletonItem::List items = prefs()->items(); + KConfigSkeletonItem::List items = prefs()->items(); - QMap mGroupPages; - QMap mGroupLayouts; - QMap mCurrentRows; - - KConfigSkeletonItem::List::ConstIterator it; - for ( it = items.constBegin(); it != items.constEnd(); ++it ) { - QString group = (*it)->group(); - //QString name = (*it)->name(); - - QWidget *page; - QGridLayout *layout; - int currentRow; - if ( !mGroupPages.contains( group ) ) { - page = new QWidget( this ); - addPage( page, group ); - layout = new QGridLayout( page ); - mGroupPages.insert( group, page ); - mGroupLayouts.insert( group, layout ); - currentRow = 0; - mCurrentRows.insert( group, currentRow ); - } else { - page = mGroupPages[ group ]; - layout = mGroupLayouts[ group ]; - currentRow = mCurrentRows[ group ]; - } - - KPrefsWid *wid = KPrefsWidFactory::create( *it, page ); - - if ( wid ) { - QList widgets = wid->widgets(); - if ( widgets.count() == 1 ) { - layout->addWidget( widgets[ 0 ], currentRow, currentRow, 0, 1 ); - } else if ( widgets.count() == 2 ) { - layout->addWidget( widgets[ 0 ], currentRow, 0 ); - layout->addWidget( widgets[ 1 ], currentRow, 1 ); - } else { - kError() <<"More widgets than expected:" << widgets.count(); - } - - if ( (*it)->isImmutable() ) { - QList::Iterator it2; - for ( it2 = widgets.begin(); it2 != widgets.end(); ++it2 ) { - (*it2)->setEnabled( false ); + QMap mGroupPages; + QMap mGroupLayouts; + QMap mCurrentRows; + + KConfigSkeletonItem::List::ConstIterator it; + for ( it = items.constBegin(); it != items.constEnd(); ++it ) { + QString group = (*it)->group(); + //QString name = (*it)->name(); + + QWidget *page; + QGridLayout *layout; + int currentRow; + if ( !mGroupPages.contains( group ) ) { + page = new QWidget( this ); + addPage( page, group ); + layout = new QGridLayout( page ); + mGroupPages.insert( group, page ); + mGroupLayouts.insert( group, layout ); + currentRow = 0; + mCurrentRows.insert( group, currentRow ); + } else { + page = mGroupPages[ group ]; + layout = mGroupLayouts[ group ]; + currentRow = mCurrentRows[ group ]; + } + + KPrefsWid *wid = KPrefsWidFactory::create( *it, page ); + + if ( wid ) { + QList widgets = wid->widgets(); + if ( widgets.count() == 1 ) { + layout->addWidget( widgets[ 0 ], currentRow, currentRow, 0, 1 ); + } else if ( widgets.count() == 2 ) { + layout->addWidget( widgets[ 0 ], currentRow, 0 ); + layout->addWidget( widgets[ 1 ], currentRow, 1 ); + } else { + kError() <<"More widgets than expected:" << widgets.count(); + } + + if ( (*it)->isImmutable() ) { + QList::Iterator it2; + for ( it2 = widgets.begin(); it2 != widgets.end(); ++it2 ) { + (*it2)->setEnabled( false ); + } + } + addWid( wid ); + mCurrentRows.insert( group, ++currentRow ); } - } - addWid( wid ); - mCurrentRows.insert( group, ++currentRow ); } - } - readConfig(); + readConfig(); } void KPrefsDialog::setDefaults() { - setWidDefaults(); + setWidDefaults(); } void KPrefsDialog::readConfig() { - readWidConfig(); - usrReadConfig(); + readWidConfig(); + usrReadConfig(); } void KPrefsDialog::writeConfig() { - writeWidConfig(); - usrWriteConfig(); - readConfig(); + writeWidConfig(); + usrWriteConfig(); + readConfig(); } void KPrefsDialog::slotApply() { - writeConfig(); + writeConfig(); - emit configChanged(); + emit configChanged(); } void KPrefsDialog::slotOk() { - slotApply(); - accept(); + slotApply(); + accept(); } void KPrefsDialog::slotDefault() { - if ( KMessageBox::warningContinueCancel( - this, - i18n( "You are about to set all preferences to default values. " - "All custom modifications will be lost." ), - i18n( "Setting Default Preferences" ), - KGuiItem( i18n( "Reset to Defaults" ) ) ) == KMessageBox::Continue ) { - setDefaults(); - } + if ( KMessageBox::warningContinueCancel( + this, + i18n( "You are about to set all preferences to default values. " + "All custom modifications will be lost." ), + i18n( "Setting Default Preferences" ), + KGuiItem( i18n( "Reset to Defaults" ) ) ) == KMessageBox::Continue ) { + setDefaults(); + } } KPrefsModule::KPrefsModule( KConfigSkeleton *prefs, const KComponentData &instance, QWidget *parent, const QVariantList &args ) - : KCModule( instance, parent, args ), - KPrefsWidManager( prefs ) + : KCModule( instance, parent, args ), + KPrefsWidManager( prefs ) { - emit changed( false ); + emit changed( false ); } void KPrefsModule::addWid( KPrefsWid *wid ) { - KPrefsWidManager::addWid( wid ); - connect( wid, SIGNAL(changed()), SLOT(slotWidChanged()) ); + KPrefsWidManager::addWid( wid ); + connect( wid, SIGNAL(changed()), SLOT(slotWidChanged()) ); } void KPrefsModule::slotWidChanged() { - emit changed( true ); + emit changed( true ); } void KPrefsModule::load() { - readWidConfig(); - usrReadConfig(); + readWidConfig(); + usrReadConfig(); - emit changed( false ); + emit changed( false ); } void KPrefsModule::save() { - writeWidConfig(); - usrWriteConfig(); + writeWidConfig(); + usrWriteConfig(); } void KPrefsModule::defaults() { - setWidDefaults(); + setWidDefaults(); - emit changed( true ); + emit changed( true ); } diff -Nru kdepim-4.12.97/libkdepim/prefs/kprefsdialog.h kdepim-4.13.0/libkdepim/prefs/kprefsdialog.h --- kdepim-4.12.97/libkdepim/prefs/kprefsdialog.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/prefs/kprefsdialog.h 2014-04-10 07:40:20.000000000 +0000 @@ -62,8 +62,8 @@ */ class KDEPIM_EXPORT KPrefsWid : public QObject { - Q_OBJECT - public: + Q_OBJECT +public: /** This function is called to read value of the setting from the stored configuration and display it in the widget. @@ -80,7 +80,7 @@ */ virtual QList widgets() const; - Q_SIGNALS: +Q_SIGNALS: /** Emitted when widget value has changed. */ @@ -95,7 +95,7 @@ */ class KDEPIM_EXPORT KPrefsWidBool : public KPrefsWid { - public: +public: /** Create a bool value control element consisting of a QCheckbox. @@ -114,7 +114,7 @@ QList widgets() const; - private: +private: KConfigSkeleton::ItemBool *mItem; QCheckBox *mCheck; @@ -129,7 +129,7 @@ */ class KDEPIM_EXPORT KPrefsWidInt : public KPrefsWid { - public: +public: /** Create a integer value control element consisting of a label and a spinbox. @@ -154,7 +154,7 @@ QList widgets() const; - private: +private: KConfigSkeleton::ItemInt *mItem; QLabel *mLabel; @@ -170,7 +170,7 @@ */ class KDEPIM_EXPORT KPrefsWidTime : public KPrefsWid { - public: +public: /** Create a time value control element consisting of a label and a spinbox. @@ -192,7 +192,7 @@ void readConfig(); void writeConfig(); - private: +private: KConfigSkeleton::ItemDateTime *mItem; QLabel *mLabel; @@ -208,7 +208,7 @@ */ class KDEPIM_EXPORT KPrefsWidDuration : public KPrefsWid { - public: +public: /** Create a duration value control element consisting of a label and a spinbox. @@ -231,7 +231,7 @@ void readConfig(); void writeConfig(); - private: +private: KConfigSkeleton::ItemDateTime *mItem; QLabel *mLabel; @@ -247,7 +247,7 @@ */ class KDEPIM_EXPORT KPrefsWidDate : public KPrefsWid { - public: +public: /** Create a time value control element consisting of a label and a date box. @@ -269,7 +269,7 @@ void readConfig(); void writeConfig(); - private: +private: KConfigSkeleton::ItemDateTime *mItem; QLabel *mLabel; @@ -285,8 +285,8 @@ */ class KDEPIM_EXPORT KPrefsWidColor : public KPrefsWid { - Q_OBJECT - public: + Q_OBJECT +public: /** Create a color value control element consisting of a test field and a button for opening a color dialog. @@ -313,7 +313,7 @@ void readConfig(); void writeConfig(); - private: +private: KConfigSkeleton::ItemColor *mItem; QLabel *mLabel; @@ -328,8 +328,8 @@ */ class KDEPIM_EXPORT KPrefsWidFont : public KPrefsWid { - Q_OBJECT - public: + Q_OBJECT +public: /** Create a font value control element consisting of a test field and a button for opening a font dialog. @@ -363,10 +363,10 @@ void readConfig(); void writeConfig(); - protected Q_SLOTS: +protected Q_SLOTS: void selectFont(); - private: +private: KConfigSkeleton::ItemFont *mItem; QLabel *mLabel; @@ -387,7 +387,7 @@ */ class KDEPIM_EXPORT KPrefsWidRadios : public KPrefsWid { - public: +public: /** Create a control element for selection of an option. It consists of a box with several radio buttons. @@ -421,7 +421,7 @@ QList widgets() const; - private: +private: KConfigSkeleton::ItemEnum *mItem; QGroupBox *mBox; @@ -440,7 +440,7 @@ */ class KDE_EXPORT KPrefsWidCombo : public KPrefsWid { - public: +public: /** Create a control element for selection of an option. It consists of a combo box. @@ -457,7 +457,7 @@ KComboBox *comboBox(); QList widgets() const; - private: +private: KConfigSkeleton::ItemEnum *mItem; KComboBox *mCombo; }; @@ -471,7 +471,7 @@ */ class KDEPIM_EXPORT KPrefsWidString : public KPrefsWid { - public: +public: /** Create a string value control element consisting of a test label and a line edit. @@ -502,7 +502,7 @@ QList widgets() const; - private: +private: KConfigSkeleton::ItemString *mItem; QLabel *mLabel; @@ -518,7 +518,7 @@ */ class KDEPIM_EXPORT KPrefsWidPath : public KPrefsWid { - public: +public: /** Create a string value control element consisting of a test label and a line edit. @@ -553,7 +553,7 @@ QList widgets() const; - private: +private: KConfigSkeleton::ItemPath *mItem; QLabel *mLabel; @@ -570,7 +570,7 @@ */ class KDEPIM_EXPORT KPrefsWidManager { - public: +public: /** Create a KPrefsWidManager object for a KPrefs object. @@ -718,7 +718,7 @@ /** Write preferences to config file. */ void writeWidConfig(); - private: +private: KConfigSkeleton *mPrefs; QList mPrefsWids; @@ -738,8 +738,8 @@ */ class KDEPIM_EXPORT KPrefsDialog : public KPageDialog, public KPrefsWidManager { - Q_OBJECT - public: + Q_OBJECT +public: /** Create a KPrefsDialog for a KPrefs object. @@ -758,7 +758,7 @@ void autoCreate(); - public Q_SLOTS: +public Q_SLOTS: /** Set all widgets to default values. */ void setDefaults(); @@ -768,11 +768,11 @@ /** Write preferences to config file. */ void writeConfig(); - Q_SIGNALS: +Q_SIGNALS: /** Emitted when the a changed configuration has been stored. */ void configChanged(); - protected Q_SLOTS: +protected Q_SLOTS: /** Apply changes to preferences */ void slotApply(); @@ -782,7 +782,7 @@ /** Set preferences to default values */ void slotDefault(); - protected: +protected: /** Implement this to read custom configuration widgets. */ virtual void usrReadConfig() {} /** Implement this to write custom configuration widgets. */ @@ -791,8 +791,8 @@ class KDEPIM_EXPORT KPrefsModule : public KCModule, public KPrefsWidManager { - Q_OBJECT - public: + Q_OBJECT +public: KPrefsModule( KConfigSkeleton *, const KComponentData &instance, QWidget *parent=0, const QVariantList &args=QVariantList() ); @@ -802,10 +802,10 @@ void save(); void defaults(); - protected Q_SLOTS: +protected Q_SLOTS: void slotWidChanged(); - protected: +protected: /** Implement this to read custom configuration widgets. */ virtual void usrReadConfig() {} /** Implement this to write custom configuration widgets. */ diff -Nru kdepim-4.12.97/libkdepim/widgets/kcheckcombobox.cpp kdepim-4.13.0/libkdepim/widgets/kcheckcombobox.cpp --- kdepim-4.12.97/libkdepim/widgets/kcheckcombobox.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/widgets/kcheckcombobox.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -41,15 +41,15 @@ class KCheckComboBox::Private { - KCheckComboBox *q; + KCheckComboBox *q; - public: +public: Private( KCheckComboBox *qq ) - : q( qq ) - , mSeparator( QLatin1Char( ',' ) ) - , mSqueezeText( false ) - , mIgnoreHide( false ) - , mAlwaysShowDefaultText( false ) + : q( qq ) + , mSeparator( QLatin1Char( ',' ) ) + , mSqueezeText( false ) + , mIgnoreHide( false ) + , mAlwaysShowDefaultText( false ) { } void makeInsertedItemsCheckable(const QModelIndex &, int start, int end); @@ -59,7 +59,7 @@ int role = Qt::DisplayRole ); void toggleCheckState(); - public: +public: QString mSeparator; QString mDefaultText; bool mSqueezeText; @@ -71,295 +71,295 @@ void KCheckComboBox::Private::makeInsertedItemsCheckable(const QModelIndex &parent, int start, int end) { - Q_UNUSED( parent ); - QStandardItemModel *model = qobject_cast( q->model() ); - if ( model ) { - for ( int r = start; r <= end; ++r ) { - QStandardItem *item = model->item( r, 0 ); - item->setCheckable( true ); - } - } else { - kWarning() << "KCheckComboBox: model is not a QStandardItemModel but a" << q->model() << ". Cannot proceed."; - } + Q_UNUSED( parent ); + QStandardItemModel *model = qobject_cast( q->model() ); + if ( model ) { + for ( int r = start; r <= end; ++r ) { + QStandardItem *item = model->item( r, 0 ); + item->setCheckable( true ); + } + } else { + kWarning() << "KCheckComboBox: model is not a QStandardItemModel but a" << q->model() << ". Cannot proceed."; + } } QString KCheckComboBox::Private::squeeze( const QString &text ) { - QFontMetrics fm( q->fontMetrics() ); - // The 4 pixels is 2 * horizontalMargin from QLineEdit. - // The rest is code from QLineEdit::paintEvent, where it determines whether to scroll the text - // (on my machine minLB=2 and minRB=2, so this removes 8 pixels in total) - const int minLB = qMax(0, -fm.minLeftBearing()); - const int minRB = qMax(0, -fm.minRightBearing()); - const int lineEditWidth = q->lineEdit()->width() - 4 - minLB - minRB; - const int textWidth = fm.width( text ); - if ( textWidth > lineEditWidth ) { - return fm.elidedText( text, Qt::ElideMiddle, lineEditWidth ); - } + QFontMetrics fm( q->fontMetrics() ); + // The 4 pixels is 2 * horizontalMargin from QLineEdit. + // The rest is code from QLineEdit::paintEvent, where it determines whether to scroll the text + // (on my machine minLB=2 and minRB=2, so this removes 8 pixels in total) + const int minLB = qMax(0, -fm.minLeftBearing()); + const int minRB = qMax(0, -fm.minRightBearing()); + const int lineEditWidth = q->lineEdit()->width() - 4 - minLB - minRB; + const int textWidth = fm.width( text ); + if ( textWidth > lineEditWidth ) { + return fm.elidedText( text, Qt::ElideMiddle, lineEditWidth ); + } - return text; + return text; } void KCheckComboBox::Private::updateCheckedItems( const QModelIndex &topLeft, const QModelIndex &bottomRight, int role ) { - Q_UNUSED( topLeft ); - Q_UNUSED( bottomRight ); + Q_UNUSED( topLeft ); + Q_UNUSED( bottomRight ); - const QStringList items = q->checkedItems( role ); - QString text; - if ( items.isEmpty() || mAlwaysShowDefaultText ) { - text = mDefaultText; - } else { - text = items.join( mSeparator ); - } + const QStringList items = q->checkedItems( role ); + QString text; + if ( items.isEmpty() || mAlwaysShowDefaultText ) { + text = mDefaultText; + } else { + text = items.join( mSeparator ); + } - if ( mSqueezeText ) - text = squeeze( text ); + if ( mSqueezeText ) + text = squeeze( text ); - q->lineEdit()->setText( text ); + q->lineEdit()->setText( text ); - emit q->checkedItemsChanged( items ); + emit q->checkedItemsChanged( items ); } void KCheckComboBox::Private::toggleCheckState() { - if (q->view()->isVisible()) { - const QModelIndex index = q->view()->currentIndex(); - QVariant value = index.data( Qt::CheckStateRole ); - if ( value.isValid() ) { - Qt::CheckState state = static_cast( value.toInt() ); - q->model()->setData( index, state == Qt::Unchecked ? Qt::Checked : Qt::Unchecked, - Qt::CheckStateRole ); + if (q->view()->isVisible()) { + const QModelIndex index = q->view()->currentIndex(); + QVariant value = index.data( Qt::CheckStateRole ); + if ( value.isValid() ) { + Qt::CheckState state = static_cast( value.toInt() ); + q->model()->setData( index, state == Qt::Unchecked ? Qt::Checked : Qt::Unchecked, + Qt::CheckStateRole ); + } } - } } /// Class KCheckComboBox KCheckComboBox::KCheckComboBox( QWidget *parent ) - : KComboBox( parent ) - , d( new KCheckComboBox::Private( this ) ) + : KComboBox( parent ) + , d( new KCheckComboBox::Private( this ) ) { - connect( this, SIGNAL(activated(int)), this, SLOT(toggleCheckState()) ); - connect( model(), SIGNAL(rowsInserted(QModelIndex,int,int)), - SLOT(makeInsertedItemsCheckable(QModelIndex,int,int)) ); - connect( model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(updateCheckedItems(QModelIndex,QModelIndex)) ); - - // read-only contents - setEditable( true ); - lineEdit()->setAlignment( Qt::AlignLeft ); - // The cast is a workaround for the fact that QLineEdit::setReadOnly isn't virtual. - // KLineEdit copes with this case since kdelibs-4.6 though. - qobject_cast(lineEdit())->setReadOnly( true ); - setInsertPolicy( KComboBox::NoInsert ); + connect( this, SIGNAL(activated(int)), this, SLOT(toggleCheckState()) ); + connect( model(), SIGNAL(rowsInserted(QModelIndex,int,int)), + SLOT(makeInsertedItemsCheckable(QModelIndex,int,int)) ); + connect( model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(updateCheckedItems(QModelIndex,QModelIndex)) ); + + // read-only contents + setEditable( true ); + lineEdit()->setAlignment( Qt::AlignLeft ); + // The cast is a workaround for the fact that QLineEdit::setReadOnly isn't virtual. + // KLineEdit copes with this case since kdelibs-4.6 though. + qobject_cast(lineEdit())->setReadOnly( true ); + setInsertPolicy( KComboBox::NoInsert ); - view()->installEventFilter( this ); - view()->viewport()->installEventFilter( this ); + view()->installEventFilter( this ); + view()->viewport()->installEventFilter( this ); - lineEdit()->installEventFilter( this ); + lineEdit()->installEventFilter( this ); - d->updateCheckedItems(); + d->updateCheckedItems(); } KCheckComboBox::~KCheckComboBox() { - delete d; + delete d; } void KCheckComboBox::hidePopup() { - if ( !d->mIgnoreHide ) { - KComboBox::hidePopup(); - } - d->mIgnoreHide = false; + if ( !d->mIgnoreHide ) { + KComboBox::hidePopup(); + } + d->mIgnoreHide = false; } Qt::CheckState KCheckComboBox::itemCheckState( int index ) const { - return static_cast( itemData( index, Qt::CheckStateRole ).toInt() ); + return static_cast( itemData( index, Qt::CheckStateRole ).toInt() ); } void KCheckComboBox::setItemCheckState( int index, Qt::CheckState state ) { - setItemData( index, state, Qt::CheckStateRole ); + setItemData( index, state, Qt::CheckStateRole ); } QStringList KCheckComboBox::checkedItems( int role ) const { - QStringList items; - if ( model() ) { - const QModelIndex index = model()->index( 0, modelColumn(), rootModelIndex() ); - const QModelIndexList indexes = model()->match( index, Qt::CheckStateRole, - Qt::Checked, -1, Qt::MatchExactly ); - foreach ( const QModelIndex &index, indexes ) { - items += index.data( role ).toString(); + QStringList items; + if ( model() ) { + const QModelIndex index = model()->index( 0, modelColumn(), rootModelIndex() ); + const QModelIndexList indexes = model()->match( index, Qt::CheckStateRole, + Qt::Checked, -1, Qt::MatchExactly ); + foreach ( const QModelIndex &index, indexes ) { + items += index.data( role ).toString(); + } } - } - return items; + return items; } void KCheckComboBox::setCheckedItems( const QStringList &items, int role ) { - for ( int r = 0; r < model()->rowCount( rootModelIndex() ); ++r ) { - const QModelIndex indx = model()->index( r, modelColumn(), rootModelIndex() ); + for ( int r = 0; r < model()->rowCount( rootModelIndex() ); ++r ) { + const QModelIndex indx = model()->index( r, modelColumn(), rootModelIndex() ); - const QString text = indx.data( role ).toString(); - const bool found = items.contains( text ); - model()->setData( indx, found ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole ); - } - d->updateCheckedItems( QModelIndex(), QModelIndex(), role ); + const QString text = indx.data( role ).toString(); + const bool found = items.contains( text ); + model()->setData( indx, found ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole ); + } + d->updateCheckedItems( QModelIndex(), QModelIndex(), role ); } QString KCheckComboBox::defaultText() const { - return d->mDefaultText; + return d->mDefaultText; } void KCheckComboBox::setDefaultText( const QString &text ) { - if ( d->mDefaultText != text ) { - d->mDefaultText = text; - d->updateCheckedItems(); - } + if ( d->mDefaultText != text ) { + d->mDefaultText = text; + d->updateCheckedItems(); + } } bool KCheckComboBox::squeezeText() const { - return d->mSqueezeText; + return d->mSqueezeText; } void KCheckComboBox::setSqueezeText( bool squeeze ) { - if ( d->mSqueezeText != squeeze ) { - d->mSqueezeText = squeeze; - d->updateCheckedItems(); - } + if ( d->mSqueezeText != squeeze ) { + d->mSqueezeText = squeeze; + d->updateCheckedItems(); + } } bool KCheckComboBox::itemEnabled( int index ) { - Q_ASSERT( index >= 0 && index <= count() ); + Q_ASSERT( index >= 0 && index <= count() ); - QStandardItemModel *itemModel = qobject_cast( model() ); - Q_ASSERT( itemModel ); + QStandardItemModel *itemModel = qobject_cast( model() ); + Q_ASSERT( itemModel ); - QStandardItem *item = itemModel->item( index, 0 ); - return item->isEnabled(); + QStandardItem *item = itemModel->item( index, 0 ); + return item->isEnabled(); } void KCheckComboBox::setItemEnabled( int index, bool enabled ) { - Q_ASSERT( index >= 0 && index <= count() ); + Q_ASSERT( index >= 0 && index <= count() ); - QStandardItemModel *itemModel = qobject_cast( model() ); - Q_ASSERT( itemModel ); + QStandardItemModel *itemModel = qobject_cast( model() ); + Q_ASSERT( itemModel ); - QStandardItem *item = itemModel->item( index, 0 ); - item->setEnabled( enabled ); + QStandardItem *item = itemModel->item( index, 0 ); + item->setEnabled( enabled ); } QString KCheckComboBox::separator() const { - return d->mSeparator; + return d->mSeparator; } void KCheckComboBox::setSeparator( const QString &separator ) { - if ( d->mSeparator != separator ) { - d->mSeparator = separator; - d->updateCheckedItems(); - } + if ( d->mSeparator != separator ) { + d->mSeparator = separator; + d->updateCheckedItems(); + } } void KCheckComboBox::keyPressEvent( QKeyEvent *event ) { - switch ( event->key() ) { + switch ( event->key() ) { case Qt::Key_Up: case Qt::Key_Down: - showPopup(); - event->accept(); - break; + showPopup(); + event->accept(); + break; case Qt::Key_Return: case Qt::Key_Enter: case Qt::Key_Escape: - hidePopup(); - event->accept(); - break; + hidePopup(); + event->accept(); + break; default: - break; - } - // don't call base class implementation, we don't need all that stuff in there + break; + } + // don't call base class implementation, we don't need all that stuff in there } #ifndef QT_NO_WHEELEVENT void KCheckComboBox::wheelEvent( QWheelEvent *event ) { - // discard mouse wheel events on the combo box - event->accept(); + // discard mouse wheel events on the combo box + event->accept(); } #endif void KCheckComboBox::resizeEvent( QResizeEvent * event ) { - KComboBox::resizeEvent( event ); - if ( d->mSqueezeText ) - d->updateCheckedItems(); + KComboBox::resizeEvent( event ); + if ( d->mSqueezeText ) + d->updateCheckedItems(); } bool KCheckComboBox::eventFilter( QObject *receiver, QEvent *event ) { - switch ( event->type() ) { + switch ( event->type() ) { case QEvent::KeyPress: case QEvent::KeyRelease: case QEvent::ShortcutOverride: { - switch ( static_cast( event )->key() ) { + switch ( static_cast( event )->key() ) { case Qt::Key_Space: - if ( event->type() == QEvent::KeyPress && view()->isVisible() ) { - d->toggleCheckState(); - } - // Always eat the event: don't let QItemDelegate toggle the current index when the view is hidden. - return true; + if ( event->type() == QEvent::KeyPress && view()->isVisible() ) { + d->toggleCheckState(); + } + // Always eat the event: don't let QItemDelegate toggle the current index when the view is hidden. + return true; case Qt::Key_Return: case Qt::Key_Enter: case Qt::Key_Escape: - // ignore Enter keys, they would normally select items. - // but we select with Space, because multiple selection is possible - // we simply close the popup on Enter/Escape - hidePopup(); - return true; - } + // ignore Enter keys, they would normally select items. + // but we select with Space, because multiple selection is possible + // we simply close the popup on Enter/Escape + hidePopup(); + return true; + } } - break; + break; case QEvent::MouseButtonDblClick: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: - d->mIgnoreHide = true; - if ( receiver == lineEdit() ) { - showPopup(); - return true; - } - break; + d->mIgnoreHide = true; + if ( receiver == lineEdit() ) { + showPopup(); + return true; + } + break; default: - break; - } - return KComboBox::eventFilter( receiver, event ); + break; + } + return KComboBox::eventFilter( receiver, event ); } bool KCheckComboBox::alwaysShowDefaultText() const { - return d->mAlwaysShowDefaultText; + return d->mAlwaysShowDefaultText; } void KCheckComboBox::setAlwaysShowDefaultText( bool always ) { - if ( always != d->mAlwaysShowDefaultText ) { - d->mAlwaysShowDefaultText = always; - d->updateCheckedItems(); - } + if ( always != d->mAlwaysShowDefaultText ) { + d->mAlwaysShowDefaultText = always; + d->updateCheckedItems(); + } } #include "moc_kcheckcombobox.cpp" diff -Nru kdepim-4.12.97/libkdepim/widgets/kcheckcombobox.h kdepim-4.13.0/libkdepim/widgets/kcheckcombobox.h --- kdepim-4.12.97/libkdepim/widgets/kcheckcombobox.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/widgets/kcheckcombobox.h 2014-04-10 07:40:20.000000000 +0000 @@ -41,14 +41,14 @@ */ class KDEPIM_EXPORT KCheckComboBox : public KComboBox { - Q_OBJECT + Q_OBJECT - Q_PROPERTY( QString separator READ separator WRITE setSeparator ) - Q_PROPERTY( QString defaultText READ defaultText WRITE setDefaultText ) - Q_PROPERTY( bool squeezeText READ squeezeText WRITE setSqueezeText ) - Q_PROPERTY( QStringList checkedItems READ checkedItems WRITE setCheckedItems ) + Q_PROPERTY( QString separator READ separator WRITE setSeparator ) + Q_PROPERTY( QString defaultText READ defaultText WRITE setDefaultText ) + Q_PROPERTY( bool squeezeText READ squeezeText WRITE setSqueezeText ) + Q_PROPERTY( QStringList checkedItems READ checkedItems WRITE setCheckedItems ) - public: +public: /** * Creates a new checkable combobox. * @@ -153,7 +153,7 @@ */ QStringList checkedItems( int role = Qt::DisplayRole ) const; - public Q_SLOTS: +public Q_SLOTS: /** * Sets the currently selected items. Items that are not found in the model * are silently ignored. @@ -163,7 +163,7 @@ */ void setCheckedItems( const QStringList &items, int role = Qt::DisplayRole ); - Q_SIGNALS: +Q_SIGNALS: /** * Signal to notify listeners that the current selections has changed. * @@ -171,7 +171,7 @@ */ void checkedItemsChanged( const QStringList &items ); - protected: +protected: virtual bool eventFilter( QObject *receiver, QEvent *event ); virtual void keyPressEvent( QKeyEvent *event ); virtual void resizeEvent( QResizeEvent * event ); @@ -179,7 +179,7 @@ virtual void wheelEvent( QWheelEvent *event ); #endif - private: +private: //@cond PRIVATE class Private; Private *const d; diff -Nru kdepim-4.12.97/libkdepim/widgets/kdatepickerpopup.cpp kdepim-4.13.0/libkdepim/widgets/kdatepickerpopup.cpp --- kdepim-4.12.97/libkdepim/widgets/kdatepickerpopup.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/widgets/kdatepickerpopup.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -31,39 +31,39 @@ class KDatePickerAction : public QWidgetAction { - public: +public: KDatePickerAction( KDatePicker *widget, QObject *parent ) - : QWidgetAction( parent ), - mDatePicker( widget ), mOriginalParent( widget->parentWidget() ) + : QWidgetAction( parent ), + mDatePicker( widget ), mOriginalParent( widget->parentWidget() ) { } - protected: +protected: QWidget *createWidget( QWidget *parent ) { - mDatePicker->setParent( parent ); - return mDatePicker; + mDatePicker->setParent( parent ); + return mDatePicker; } void deleteWidget( QWidget *widget ) { - if ( widget != mDatePicker ) { - return; - } + if ( widget != mDatePicker ) { + return; + } - mDatePicker->setParent( mOriginalParent ); + mDatePicker->setParent( mOriginalParent ); } - private: +private: KDatePicker *mDatePicker; QWidget *mOriginalParent; }; class KDatePickerPopup::Private { - public: +public: Private( KDatePickerPopup *qq ) - : q( qq ), mDatePicker( 0 ) + : q( qq ), mDatePicker( 0 ) { } @@ -83,95 +83,95 @@ void KDatePickerPopup::Private::buildMenu() { - if ( q->isVisible() ) - return; + if ( q->isVisible() ) + return; - q->clear(); + q->clear(); - if ( mModes & DatePicker ) { - q->addAction( new KDatePickerAction( mDatePicker, q ) ); + if ( mModes & DatePicker ) { + q->addAction( new KDatePickerAction( mDatePicker, q ) ); - if ( (mModes & NoDate) || (mModes & Words) ) - q->addSeparator(); - } - - if ( mModes & Words ) { - q->addAction( i18nc( "@option today", "&Today" ), q, SLOT(slotToday()) ); - q->addAction( i18nc( "@option tomorrow", "To&morrow" ), q, SLOT(slotTomorrow()) ); - q->addAction( i18nc( "@option next week", "Next &Week" ), q, SLOT(slotNextWeek()) ); - q->addAction( i18nc( "@option next month", "Next M&onth" ), q, SLOT(slotNextMonth()) ); + if ( (mModes & NoDate) || (mModes & Words) ) + q->addSeparator(); + } - if ( mModes & NoDate ) - q->addSeparator(); - } + if ( mModes & Words ) { + q->addAction( i18nc( "@option today", "&Today" ), q, SLOT(slotToday()) ); + q->addAction( i18nc( "@option tomorrow", "To&morrow" ), q, SLOT(slotTomorrow()) ); + q->addAction( i18nc( "@option next week", "Next &Week" ), q, SLOT(slotNextWeek()) ); + q->addAction( i18nc( "@option next month", "Next M&onth" ), q, SLOT(slotNextMonth()) ); - if ( mModes & NoDate ) - q->addAction( i18nc( "@option do not specify a date", "No Date" ), q, SLOT(slotNoDate()) ); + if ( mModes & NoDate ) + q->addSeparator(); + } + + if ( mModes & NoDate ) + q->addAction( i18nc( "@option do not specify a date", "No Date" ), q, SLOT(slotNoDate()) ); } void KDatePickerPopup::Private::slotDateChanged( const QDate &date ) { - emit q->dateChanged( date ); - q->hide(); + emit q->dateChanged( date ); + q->hide(); } void KDatePickerPopup::Private::slotToday() { - emit q->dateChanged( QDate::currentDate() ); + emit q->dateChanged( QDate::currentDate() ); } void KDatePickerPopup::Private::slotTomorrow() { - emit q->dateChanged( QDate::currentDate().addDays( 1 ) ); + emit q->dateChanged( QDate::currentDate().addDays( 1 ) ); } void KDatePickerPopup::Private::slotNoDate() { - emit q->dateChanged( QDate() ); + emit q->dateChanged( QDate() ); } void KDatePickerPopup::Private::slotNextWeek() { - emit q->dateChanged( QDate::currentDate().addDays( 7 ) ); + emit q->dateChanged( QDate::currentDate().addDays( 7 ) ); } void KDatePickerPopup::Private::slotNextMonth() { - emit q->dateChanged( QDate::currentDate().addMonths( 1 ) ); + emit q->dateChanged( QDate::currentDate().addMonths( 1 ) ); } KDatePickerPopup::KDatePickerPopup( Modes modes, const QDate &date, QWidget *parent ) - : QMenu( parent ), d( new Private( this ) ) + : QMenu( parent ), d( new Private( this ) ) { - d->mModes = modes; + d->mModes = modes; - d->mDatePicker = new KDatePicker( this ); - d->mDatePicker->setCloseButton( false ); + d->mDatePicker = new KDatePicker( this ); + d->mDatePicker->setCloseButton( false ); - connect( d->mDatePicker, SIGNAL(dateEntered(QDate)), - SLOT(slotDateChanged(QDate)) ); - connect( d->mDatePicker, SIGNAL(dateSelected(QDate)), - SLOT(slotDateChanged(QDate)) ); + connect( d->mDatePicker, SIGNAL(dateEntered(QDate)), + SLOT(slotDateChanged(QDate)) ); + connect( d->mDatePicker, SIGNAL(dateSelected(QDate)), + SLOT(slotDateChanged(QDate)) ); - d->mDatePicker->setDate( date ); + d->mDatePicker->setDate( date ); - d->buildMenu(); + d->buildMenu(); } KDatePickerPopup::~KDatePickerPopup() { - delete d; + delete d; } KDatePicker *KDatePickerPopup::datePicker() const { - return d->mDatePicker; + return d->mDatePicker; } void KDatePickerPopup::setDate( const QDate &date ) { - d->mDatePicker->setDate( date ); + d->mDatePicker->setDate( date ); } #include "moc_kdatepickerpopup.cpp" diff -Nru kdepim-4.12.97/libkdepim/widgets/kdatepickerpopup.h kdepim-4.13.0/libkdepim/widgets/kdatepickerpopup.h --- kdepim-4.12.97/libkdepim/widgets/kdatepickerpopup.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/widgets/kdatepickerpopup.h 2014-04-10 07:40:20.000000000 +0000 @@ -47,17 +47,17 @@ */ class KDEPIM_EXPORT KDatePickerPopup: public QMenu { - Q_OBJECT + Q_OBJECT - public: +public: /** * Describes the available selection modes. */ enum Mode { - NoDate = 1, ///< A menu-item with "No Date". Will always return an invalid date. - DatePicker = 2, ///< A menu-item with a KDatePicker. - Words = 4 ///< A menu-item with list of words that describe a date. + NoDate = 1, ///< A menu-item with "No Date". Will always return an invalid date. + DatePicker = 2, ///< A menu-item with a KDatePicker. + Words = 4 ///< A menu-item with list of words that describe a date. }; /** @@ -86,13 +86,13 @@ */ KDatePicker *datePicker() const; - public Q_SLOTS: +public Q_SLOTS: /** * Sets the current @p date. */ void setDate( const QDate &date ); - Q_SIGNALS: +Q_SIGNALS: /** * This signal is emitted whenever the user has selected a new date. * @@ -100,7 +100,7 @@ */ void dateChanged( const QDate &date ); - private: +private: //@cond PRIVATE class Private; Private* const d; diff -Nru kdepim-4.12.97/libkdepim/widgets/kweekdaycheckcombo.cpp kdepim-4.13.0/libkdepim/widgets/kweekdaycheckcombo.cpp --- kdepim-4.12.97/libkdepim/widgets/kweekdaycheckcombo.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/widgets/kweekdaycheckcombo.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -30,24 +30,24 @@ KWeekdayCheckCombo::KWeekdayCheckCombo(QWidget* parent,bool first5Checked ): KCheckComboBox( parent ) { - const KCalendarSystem *calSys = KGlobal::locale()->calendar(); - const int weekStart = KGlobal::locale()->weekStartDay(); - QStringList checkedItems; - for ( int i = 0; i < 7; ++i ) { - // i is the nr of the combobox, not the day of week! - const int dayOfWeek = ( i + weekStart + 6 ) % 7; - - const QString weekDayName = calSys->weekDayName( dayOfWeek + 1, KCalendarSystem::ShortDayName ); - addItem( weekDayName ); - // by default Monday - Friday should be checked - // which corresponds to index 0 - 4; - if ( first5Checked && dayOfWeek < 5 ) { - checkedItems << weekDayName; + const KCalendarSystem *calSys = KGlobal::locale()->calendar(); + const int weekStart = KGlobal::locale()->weekStartDay(); + QStringList checkedItems; + for ( int i = 0; i < 7; ++i ) { + // i is the nr of the combobox, not the day of week! + const int dayOfWeek = ( i + weekStart + 6 ) % 7; + + const QString weekDayName = calSys->weekDayName( dayOfWeek + 1, KCalendarSystem::ShortDayName ); + addItem( weekDayName ); + // by default Monday - Friday should be checked + // which corresponds to index 0 - 4; + if ( first5Checked && dayOfWeek < 5 ) { + checkedItems << weekDayName; + } + } + if ( first5Checked ) { + setCheckedItems( checkedItems ); } - } - if ( first5Checked ) { - setCheckedItems( checkedItems ); - } } @@ -57,52 +57,52 @@ QBitArray KWeekdayCheckCombo::days() const { - QBitArray days( 7 ); - const int weekStart = KGlobal::locale()->weekStartDay(); + QBitArray days( 7 ); + const int weekStart = KGlobal::locale()->weekStartDay(); - for ( int i = 0; i < 7; ++i ) { - // i is the nr of the combobox, not the day of week! - const int index = ( 1 + i + ( 7 - weekStart ) ) % 7; - days.setBit( i, itemCheckState( index ) == Qt::Checked ); - } + for ( int i = 0; i < 7; ++i ) { + // i is the nr of the combobox, not the day of week! + const int index = ( 1 + i + ( 7 - weekStart ) ) % 7; + days.setBit( i, itemCheckState( index ) == Qt::Checked ); + } - return days; + return days; } int KWeekdayCheckCombo::weekdayIndex( const QDate &date ) const { - if ( !date.isValid() ) - return -1; - const int weekStart = KGlobal::locale()->weekStartDay(); - const KCalendarSystem *calSys = KGlobal::locale()->calendar(); - const int dayOfWeek = calSys->dayOfWeek( date ) - 1; // Values 1 - 7, we need 0 - 6 - - // kDebug() << "dayOfWeek = " << dayOfWeek << " weekStart = " << weekStart - // << "; result " << ( ( dayOfWeek + weekStart ) % 7 ) << "; date = " << date; - return ( 1 + dayOfWeek + ( 7 - weekStart ) ) % 7; + if ( !date.isValid() ) + return -1; + const int weekStart = KGlobal::locale()->weekStartDay(); + const KCalendarSystem *calSys = KGlobal::locale()->calendar(); + const int dayOfWeek = calSys->dayOfWeek( date ) - 1; // Values 1 - 7, we need 0 - 6 + + // kDebug() << "dayOfWeek = " << dayOfWeek << " weekStart = " << weekStart + // << "; result " << ( ( dayOfWeek + weekStart ) % 7 ) << "; date = " << date; + return ( 1 + dayOfWeek + ( 7 - weekStart ) ) % 7; } void KWeekdayCheckCombo::setDays( const QBitArray &days, const QBitArray &disableDays ) { - Q_ASSERT( count() == 7 ); // The combobox must be filled. - - QStringList checkedDays; - const int weekStart = KGlobal::locale()->weekStartDay(); - for ( int i = 0; i < 7; ++i ) { - // i is the nr of the combobox, not the day of week! - const int index = ( 1 + i + ( 7 - weekStart ) ) % 7; + Q_ASSERT( count() == 7 ); // The combobox must be filled. - // kDebug() << "Checking for i = " << i << "; index = " << index << days.testBit( i ); - // kDebug() << "Disabling? for i = " << i << "; index = " << index << !disableDays.testBit( i ); - - if ( days.testBit( i ) ) { - checkedDays << itemText( index ); - } - if( !disableDays.isEmpty() ) { - setItemEnabled( index, !disableDays.testBit( i ) ); + QStringList checkedDays; + const int weekStart = KGlobal::locale()->weekStartDay(); + for ( int i = 0; i < 7; ++i ) { + // i is the nr of the combobox, not the day of week! + const int index = ( 1 + i + ( 7 - weekStart ) ) % 7; + + // kDebug() << "Checking for i = " << i << "; index = " << index << days.testBit( i ); + // kDebug() << "Disabling? for i = " << i << "; index = " << index << !disableDays.testBit( i ); + + if ( days.testBit( i ) ) { + checkedDays << itemText( index ); + } + if( !disableDays.isEmpty() ) { + setItemEnabled( index, !disableDays.testBit( i ) ); + } } - } - setCheckedItems( checkedDays ); + setCheckedItems( checkedDays ); } diff -Nru kdepim-4.12.97/libkdepim/widgets/kweekdaycheckcombo.h kdepim-4.13.0/libkdepim/widgets/kweekdaycheckcombo.h --- kdepim-4.12.97/libkdepim/widgets/kweekdaycheckcombo.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/widgets/kweekdaycheckcombo.h 2014-04-10 07:40:20.000000000 +0000 @@ -41,9 +41,9 @@ class KDEPIM_EXPORT KWeekdayCheckCombo : public KCheckComboBox { - Q_OBJECT + Q_OBJECT public: - /** + /** * @param first5Checked if true the first 5 weekdays will be checked by default */ explicit KWeekdayCheckCombo( QWidget *parent = 0, bool first5Checked = false ); diff -Nru kdepim-4.12.97/libkdepim/widgets/kwidgetlister.cpp kdepim-4.13.0/libkdepim/widgets/kwidgetlister.cpp --- kdepim-4.12.97/libkdepim/widgets/kwidgetlister.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/widgets/kwidgetlister.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -48,25 +48,25 @@ class KWidgetLister::Private { - public: +public: Private( KWidgetLister *qq ) - : q( qq ), - mBtnMore( 0 ), - mBtnFewer( 0 ), - mBtnClear( 0 ), - mLayout( 0 ), - mButtonBox( 0 ), - mMinWidgets( 0 ), - mMaxWidgets( 0 ) + : q( qq ), + mBtnMore( 0 ), + mBtnFewer( 0 ), + mBtnClear( 0 ), + mLayout( 0 ), + mButtonBox( 0 ), + mMinWidgets( 0 ), + mMaxWidgets( 0 ) + - { } ~Private() { - qDeleteAll( mWidgetList ); - mWidgetList.clear(); + qDeleteAll( mWidgetList ); + mWidgetList.clear(); } void enableControls(); @@ -82,217 +82,217 @@ void KWidgetLister::Private::enableControls() { - const int count = mWidgetList.count(); - const bool isMaxWidgets = ( count >= mMaxWidgets ); - const bool isMinWidgets = ( count <= mMinWidgets ); - if ( mBtnMore ) - mBtnMore->setEnabled( !isMaxWidgets ); - if ( mBtnFewer ) - mBtnFewer->setEnabled( !isMinWidgets ); + const int count = mWidgetList.count(); + const bool isMaxWidgets = ( count >= mMaxWidgets ); + const bool isMinWidgets = ( count <= mMinWidgets ); + if ( mBtnMore ) + mBtnMore->setEnabled( !isMaxWidgets ); + if ( mBtnFewer ) + mBtnFewer->setEnabled( !isMinWidgets ); } KWidgetLister::KWidgetLister( bool fewerMoreButton, int minWidgets, int maxWidgets, QWidget *parent ) - : QWidget( parent ), d( new Private( this ) ) + : QWidget( parent ), d( new Private( this ) ) { - d->mMinWidgets = qMax( minWidgets, 1 ); - d->mMaxWidgets = qMax( maxWidgets, d->mMinWidgets + 1 ); - init( fewerMoreButton ); + d->mMinWidgets = qMax( minWidgets, 1 ); + d->mMaxWidgets = qMax( maxWidgets, d->mMinWidgets + 1 ); + init( fewerMoreButton ); } KWidgetLister::KWidgetLister( int minWidgets, int maxWidgets, QWidget *parent ) - : QWidget( parent ), d( new Private( this ) ) + : QWidget( parent ), d( new Private( this ) ) { - d->mMinWidgets = qMax( minWidgets, 1 ); - d->mMaxWidgets = qMax( maxWidgets, d->mMinWidgets + 1 ); - init(); + d->mMinWidgets = qMax( minWidgets, 1 ); + d->mMaxWidgets = qMax( maxWidgets, d->mMinWidgets + 1 ); + init(); } KWidgetLister::~KWidgetLister() { - delete d; + delete d; } void KWidgetLister::init( bool fewerMoreButton ) { //--------- the button box - d->mLayout = new QVBoxLayout( this ); - d->mLayout->setMargin( 0 ); - d->mLayout->setSpacing( 4 ); - - d->mButtonBox = new KHBox( this ); - d->mButtonBox->setSpacing( KDialog::spacingHint() ); - d->mLayout->addWidget( d->mButtonBox ); - - if ( fewerMoreButton ) - { - d->mBtnMore = new KPushButton( KGuiItem( i18nc( "more widgets", "More" ), - QLatin1String("list-add") ), d->mButtonBox ); - d->mButtonBox->setStretchFactor( d->mBtnMore, 0 ); - - d->mBtnFewer = new KPushButton( KGuiItem( i18nc( "fewer widgets", "Fewer" ), - QLatin1String("list-remove") ), d->mButtonBox ); - d->mButtonBox->setStretchFactor( d->mBtnFewer, 0 ); - } - QWidget *spacer = new QWidget( d->mButtonBox ); - d->mButtonBox->setStretchFactor( spacer, 1 ); - - d->mBtnClear = new KPushButton( KStandardGuiItem::clear(), d->mButtonBox ); - // FIXME a useful whats this. KStandardGuiItem::clear() returns a text with an edit box - d->mBtnClear->setWhatsThis( QString() ); - d->mButtonBox->setStretchFactor( d->mBtnClear, 0 ); - - //---------- connect everything - if ( fewerMoreButton ) - { - connect( d->mBtnMore, SIGNAL(clicked()), - this, SLOT(slotMore()) ); - connect( d->mBtnFewer, SIGNAL(clicked()), - this, SLOT(slotFewer()) ); - } - - connect( d->mBtnClear, SIGNAL(clicked()), - this, SLOT(slotClear()) ); + d->mLayout = new QVBoxLayout( this ); + d->mLayout->setMargin( 0 ); + d->mLayout->setSpacing( 4 ); + + d->mButtonBox = new KHBox( this ); + d->mButtonBox->setSpacing( KDialog::spacingHint() ); + d->mLayout->addWidget( d->mButtonBox ); + + if ( fewerMoreButton ) + { + d->mBtnMore = new KPushButton( KGuiItem( i18nc( "more widgets", "More" ), + QLatin1String("list-add") ), d->mButtonBox ); + d->mButtonBox->setStretchFactor( d->mBtnMore, 0 ); + + d->mBtnFewer = new KPushButton( KGuiItem( i18nc( "fewer widgets", "Fewer" ), + QLatin1String("list-remove") ), d->mButtonBox ); + d->mButtonBox->setStretchFactor( d->mBtnFewer, 0 ); + } + QWidget *spacer = new QWidget( d->mButtonBox ); + d->mButtonBox->setStretchFactor( spacer, 1 ); + + d->mBtnClear = new KPushButton( KStandardGuiItem::clear(), d->mButtonBox ); + // FIXME a useful whats this. KStandardGuiItem::clear() returns a text with an edit box + d->mBtnClear->setWhatsThis( QString() ); + d->mButtonBox->setStretchFactor( d->mBtnClear, 0 ); - d->enableControls(); + //---------- connect everything + if ( fewerMoreButton ) + { + connect( d->mBtnMore, SIGNAL(clicked()), + this, SLOT(slotMore()) ); + connect( d->mBtnFewer, SIGNAL(clicked()), + this, SLOT(slotFewer()) ); + } + + connect( d->mBtnClear, SIGNAL(clicked()), + this, SLOT(slotClear()) ); + + d->enableControls(); } void KWidgetLister::slotMore() { - // the class should make certain that slotMore can't - // be called when mMaxWidgets are on screen. - assert( (int)d->mWidgetList.count() < d->mMaxWidgets ); - - addWidgetAtEnd(); - // adjustSize(); - d->enableControls(); + // the class should make certain that slotMore can't + // be called when mMaxWidgets are on screen. + assert( (int)d->mWidgetList.count() < d->mMaxWidgets ); + + addWidgetAtEnd(); + // adjustSize(); + d->enableControls(); } void KWidgetLister::slotFewer() { - // the class should make certain that slotFewer can't - // be called when mMinWidgets are on screen. - assert( (int)d->mWidgetList.count() > d->mMinWidgets ); - - removeLastWidget(); - // adjustSize(); - d->enableControls(); + // the class should make certain that slotFewer can't + // be called when mMinWidgets are on screen. + assert( (int)d->mWidgetList.count() > d->mMinWidgets ); + + removeLastWidget(); + // adjustSize(); + d->enableControls(); } void KWidgetLister::slotClear() { - setNumberOfShownWidgetsTo( d->mMinWidgets ); + setNumberOfShownWidgetsTo( d->mMinWidgets ); - // clear remaining widgets - foreach ( QWidget *widget, d->mWidgetList ) - clearWidget( widget ); - - // adjustSize(); - d->enableControls(); - emit clearWidgets(); + // clear remaining widgets + foreach ( QWidget *widget, d->mWidgetList ) + clearWidget( widget ); + + // adjustSize(); + d->enableControls(); + emit clearWidgets(); } void KWidgetLister::addWidgetAtEnd( QWidget *widget ) { - if ( !widget ) - widget = this->createWidget( this ); + if ( !widget ) + widget = this->createWidget( this ); - d->mLayout->insertWidget( d->mLayout->indexOf( d->mButtonBox ), widget ); - d->mWidgetList.append( widget ); - widget->show(); - - d->enableControls(); - emit widgetAdded(); - emit widgetAdded( widget ); + d->mLayout->insertWidget( d->mLayout->indexOf( d->mButtonBox ), widget ); + d->mWidgetList.append( widget ); + widget->show(); + + d->enableControls(); + emit widgetAdded(); + emit widgetAdded( widget ); } void KWidgetLister::removeLastWidget() { - // The layout will take care that the - // widget is removed from screen, too. - delete d->mWidgetList.takeLast(); - d->enableControls(); - emit widgetRemoved(); + // The layout will take care that the + // widget is removed from screen, too. + delete d->mWidgetList.takeLast(); + d->enableControls(); + emit widgetRemoved(); } void KWidgetLister::clearWidget( QWidget *widget ) { - Q_UNUSED( widget ); + Q_UNUSED( widget ); } QWidget *KWidgetLister::createWidget( QWidget *parent ) { - return new QWidget( parent ); + return new QWidget( parent ); } void KWidgetLister::setNumberOfShownWidgetsTo( int aNum ) { - int superfluousWidgets = qMax( (int)d->mWidgetList.count() - aNum, 0 ); - int missingWidgets = qMax( aNum - (int)d->mWidgetList.count(), 0 ); + int superfluousWidgets = qMax( (int)d->mWidgetList.count() - aNum, 0 ); + int missingWidgets = qMax( aNum - (int)d->mWidgetList.count(), 0 ); - // remove superfluous widgets - for ( ; superfluousWidgets ; superfluousWidgets-- ) { - removeLastWidget(); - } + // remove superfluous widgets + for ( ; superfluousWidgets ; superfluousWidgets-- ) { + removeLastWidget(); + } - // add missing widgets - for ( ; missingWidgets ; missingWidgets-- ) { - addWidgetAtEnd(); - } + // add missing widgets + for ( ; missingWidgets ; missingWidgets-- ) { + addWidgetAtEnd(); + } } QList KWidgetLister::widgets() const { - return d->mWidgetList; + return d->mWidgetList; } int KWidgetLister::widgetsMinimum() const { - return d->mMinWidgets; + return d->mMinWidgets; } int KWidgetLister::widgetsMaximum() const { - return d->mMaxWidgets; + return d->mMaxWidgets; } void KWidgetLister::removeWidget(QWidget*widget) { - // The layout will take care that the - // widget is removed from screen, too. + // The layout will take care that the + // widget is removed from screen, too. + + if ( d->mWidgetList.count() <= widgetsMinimum() ) + return; - if ( d->mWidgetList.count() <= widgetsMinimum() ) - return; - - const int index = d->mWidgetList.indexOf( widget ); - QWidget* w = d->mWidgetList.takeAt(index); - w->deleteLater(); - w = 0; - d->enableControls(); - emit widgetRemoved( widget ); - emit widgetRemoved(); + const int index = d->mWidgetList.indexOf( widget ); + QWidget* w = d->mWidgetList.takeAt(index); + w->deleteLater(); + w = 0; + d->enableControls(); + emit widgetRemoved( widget ); + emit widgetRemoved(); } void KWidgetLister::addWidgetAfterThisWidget(QWidget*currentWidget, QWidget* widget) { - if ( !widget ) - widget = this->createWidget( this ); + if ( !widget ) + widget = this->createWidget( this ); + + int index = d->mLayout->indexOf( currentWidget ? currentWidget : d->mButtonBox )+1; + d->mLayout->insertWidget( index, widget ); + index = 0; + if (currentWidget) { + index = d->mWidgetList.indexOf(currentWidget); + d->mWidgetList.insert(index+1, widget); + } else { + d->mWidgetList.append(widget); + } + widget->show(); - int index = d->mLayout->indexOf( currentWidget ? currentWidget : d->mButtonBox )+1; - d->mLayout->insertWidget( index, widget ); - index = 0; - if (currentWidget) { - index = d->mWidgetList.indexOf(currentWidget); - d->mWidgetList.insert(index+1, widget); - } else { - d->mWidgetList.append(widget); - } - widget->show(); - - d->enableControls(); - emit widgetAdded(); - emit widgetAdded( widget ); + d->enableControls(); + emit widgetAdded(); + emit widgetAdded( widget ); } diff -Nru kdepim-4.12.97/libkdepim/widgets/kwidgetlister.h kdepim-4.13.0/libkdepim/widgets/kwidgetlister.h --- kdepim-4.12.97/libkdepim/widgets/kwidgetlister.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/widgets/kwidgetlister.h 2014-04-10 07:40:20.000000000 +0000 @@ -62,9 +62,9 @@ class KDEPIM_EXPORT KWidgetLister : public QWidget { - Q_OBJECT + Q_OBJECT - public: +public: //TODO KDE5 merge two constructors /** * Creates a new widget lister. @@ -89,7 +89,7 @@ */ virtual ~KWidgetLister(); - protected Q_SLOTS: +protected Q_SLOTS: /** * Called whenever the user clicks on the 'more' button. * Reimplementations should call this method, because this @@ -117,7 +117,7 @@ */ virtual void slotClear(); - protected: +protected: /** * Adds a single widget. Doesn't care if there are already @ref * mMaxWidgets on screen and whether it should enable/disable any @@ -184,10 +184,10 @@ */ virtual void addWidgetAfterThisWidget(QWidget*currentWidget, QWidget* widget = 0); - private: +private: void init( bool fewerMoreButton = true ); - Q_SIGNALS: +Q_SIGNALS: /** * This signal is emitted whenever a widget was added. */ @@ -205,7 +205,7 @@ */ void widgetRemoved(); - /** + /** * This signal is emitted whenever a widget was removed. */ void widgetRemoved( QWidget *widget ); @@ -215,7 +215,7 @@ */ void clearWidgets(); - private: +private: //@cond PRIVATE class Private; Private* const d; diff -Nru kdepim-4.12.97/libkdepim/widgets/pimmessagebox.cpp kdepim-4.13.0/libkdepim/widgets/pimmessagebox.cpp --- kdepim-4.12.97/libkdepim/widgets/pimmessagebox.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/widgets/pimmessagebox.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -35,37 +35,37 @@ const KGuiItem &button3, KMessageBox::Options options ) { - KDialog *dialog= new KDialog( parent ); - dialog->setCaption( caption ); - dialog->setButtons( KDialog::Yes | KDialog::No | KDialog::Ok | KDialog::Cancel ); - dialog->setObjectName( QLatin1String("PIMMessageBox") ); - dialog->setDefaultButton( KDialog::Yes ); - dialog->setButtonGuiItem( KDialog::Ok, button3 ); - dialog->setButtonGuiItem( KDialog::Yes, button1 ); - dialog->setButtonGuiItem( KDialog::No, button2 ); -// QObject::connect( dialog, SIGNAL(yesClicked()), dialog, SLOT(slotYes())); -// QObject::connect( dialog, SIGNAL(noClicked()), dialog, SLOT(slotNo())); + KDialog *dialog= new KDialog( parent ); + dialog->setCaption( caption ); + dialog->setButtons( KDialog::Yes | KDialog::No | KDialog::Ok | KDialog::Cancel ); + dialog->setObjectName( QLatin1String("PIMMessageBox") ); + dialog->setDefaultButton( KDialog::Yes ); + dialog->setButtonGuiItem( KDialog::Ok, button3 ); + dialog->setButtonGuiItem( KDialog::Yes, button1 ); + dialog->setButtonGuiItem( KDialog::No, button2 ); + // QObject::connect( dialog, SIGNAL(yesClicked()), dialog, SLOT(slotYes())); + // QObject::connect( dialog, SIGNAL(noClicked()), dialog, SLOT(slotNo())); - bool checkboxResult = false; - int result = KMessageBox::createKMessageBox( - dialog, type, text, QStringList(), QString(), &checkboxResult, options ); + bool checkboxResult = false; + int result = KMessageBox::createKMessageBox( + dialog, type, text, QStringList(), QString(), &checkboxResult, options ); - switch (result) { - case KDialog::Yes: - result = KMessageBox::Yes; - break; - case KDialog::No: - result = KMessageBox::No; - break; - case KDialog::Ok: - result = KMessageBox::Continue; - break; - case KDialog::Cancel: - result = KMessageBox::Cancel; - break; - default: - break; - } + switch (result) { + case KDialog::Yes: + result = KMessageBox::Yes; + break; + case KDialog::No: + result = KMessageBox::No; + break; + case KDialog::Ok: + result = KMessageBox::Continue; + break; + case KDialog::Cancel: + result = KMessageBox::Cancel; + break; + default: + break; + } - return result; + return result; } diff -Nru kdepim-4.12.97/libkdepim/widgets/pimmessagebox.h kdepim-4.13.0/libkdepim/widgets/pimmessagebox.h --- kdepim-4.12.97/libkdepim/widgets/pimmessagebox.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkdepim/widgets/pimmessagebox.h 2014-04-10 07:40:20.000000000 +0000 @@ -34,7 +34,7 @@ class KDEPIM_EXPORT PIMMessageBox { - public: +public: static int fourBtnMsgBox( QWidget *parent, QMessageBox::Icon type, const QString &text, const QString &caption = QString(), diff -Nru kdepim-4.12.97/libkleo/CMakeLists.txt kdepim-4.13.0/libkleo/CMakeLists.txt --- kdepim-4.12.97/libkleo/CMakeLists.txt 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkleo/CMakeLists.txt 2014-04-10 07:40:20.000000000 +0000 @@ -83,7 +83,6 @@ ui/cryptoconfigmodule.cpp ui/cryptoconfigdialog.cpp ui/directoryserviceswidget.cpp - ui/adddirectoryservicedialogimpl.cpp ui/progressbar.cpp ui/progressdialog.cpp ) @@ -96,7 +95,6 @@ ) kde4_add_ui_files(libkleo_ui_common_SRCS - ui/adddirectoryservicedialog.ui ui/directoryserviceswidget.ui ) diff -Nru kdepim-4.12.97/libkleo/ui/adddirectoryservicedialogimpl.cpp kdepim-4.13.0/libkleo/ui/adddirectoryservicedialogimpl.cpp --- kdepim-4.12.97/libkleo/ui/adddirectoryservicedialogimpl.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkleo/ui/adddirectoryservicedialogimpl.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -/* - adddirectoryservicedialogimpl.cpp - - This file is part of Kleopatra, the KDE keymanager - Copyright (c) 2001,2002,2004 Klarälvdalens Datakonsult AB - - Kleopatra is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - Kleopatra is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - In addition, as a special exception, the copyright holders give - permission to link the code of this program with any edition of - the Qt library by Trolltech AS, Norway (or with modified versions - of Qt that use the same license as Qt), and distribute linked - combinations including the two. You must obey the GNU General - Public License in all respects for all of the code used other than - Qt. If you modify this file, you may extend this exception to - your version of the file, but you are not obligated to do so. If - you do not wish to do so, delete this exception statement from - your version. -*/ - - -#include "adddirectoryservicedialogimpl.h" - -#include -#include - -/* - * Constructs a AddDirectoryServiceDialogImpl which is a child of 'parent', with the - * name 'name' and widget flags set to 'f' - * - * The dialog will by default be modeless, unless you set 'modal' to - * TRUE to construct a modal dialog. - */ -AddDirectoryServiceDialogImpl::AddDirectoryServiceDialogImpl( QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl ) - : QDialog(parent, fl), AddDirectoryServiceDialog() -{ - setObjectName( QLatin1String(name) ); - setModal( modal ); - setupUi(this); - portED->setValidator( new QIntValidator( 0, 65535, portED ) ); - connect(PushButton3, SIGNAL(clicked()), SLOT(slotAccept())); - connect(PushButton4, SIGNAL(clicked()), SLOT(slotCancel())); -} - -/* - * Destroys the object and frees any allocated resources - */ -AddDirectoryServiceDialogImpl::~AddDirectoryServiceDialogImpl() -{ - // no need to delete child widgets, Qt does it all for us -} - -void AddDirectoryServiceDialogImpl::slotAccept() -{ - accept(); -} - -void AddDirectoryServiceDialogImpl::slotCancel() -{ - reject(); -} - - diff -Nru kdepim-4.12.97/libkleo/ui/adddirectoryservicedialogimpl.h kdepim-4.13.0/libkleo/ui/adddirectoryservicedialogimpl.h --- kdepim-4.12.97/libkleo/ui/adddirectoryservicedialogimpl.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkleo/ui/adddirectoryservicedialogimpl.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -/* - adddirectoryservicedialogimpl.h - - This file is part of Kleopatra, the KDE keymanager - Copyright (c) 2001,2002,2004 Klarälvdalens Datakonsult AB - - Kleopatra is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - Kleopatra is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - In addition, as a special exception, the copyright holders give - permission to link the code of this program with any edition of - the Qt library by Trolltech AS, Norway (or with modified versions - of Qt that use the same license as Qt), and distribute linked - combinations including the two. You must obey the GNU General - Public License in all respects for all of the code used other than - Qt. If you modify this file, you may extend this exception to - your version of the file, but you are not obligated to do so. If - you do not wish to do so, delete this exception statement from - your version. -*/ - -#ifndef ADDDIRECTORYSERVICEDIALOGIMPL_H -#define ADDDIRECTORYSERVICEDIALOGIMPL_H -#include "ui_adddirectoryservicedialog.h" - -class AddDirectoryServiceDialogImpl : public QDialog, public Ui::AddDirectoryServiceDialog -{ - Q_OBJECT - -public: - explicit AddDirectoryServiceDialogImpl( QWidget* parent = 0, const char* name = 0, bool modal = false, Qt::WindowFlags fl = 0 ); - ~AddDirectoryServiceDialogImpl(); -private Q_SLOTS: - void slotAccept(); - void slotCancel(); -}; - -#endif // ADDDIRECTORYSERVICEDIALOGIMPL_H diff -Nru kdepim-4.12.97/libkleo/ui/adddirectoryservicedialog.ui kdepim-4.13.0/libkleo/ui/adddirectoryservicedialog.ui --- kdepim-4.12.97/libkleo/ui/adddirectoryservicedialog.ui 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkleo/ui/adddirectoryservicedialog.ui 1970-01-01 00:00:00.000000000 +0000 @@ -1,170 +0,0 @@ - - AddDirectoryServiceDialog - - - - 0 - 0 - 389 - 249 - - - - Add or Change Directory Service - - - - 11 - - - 6 - - - - - &Server name: - - - serverNameED - - - - - - - - - - 389 - - - - - - - - - - &User name (optional): - - - usernameED - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 60 - - - - - - - - Pass&word (optional): - - - passwordED - - - - - - - &OK - - - true - - - - - - - &Cancel - - - - - - - QFrame::HLine - - - QFrame::Sunken - - - Qt::Horizontal - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 260 - 21 - - - - - - - - - - - QLineEdit::Password - - - - - - - &Base DN: - - - descriptionED - - - - - - - &Port: - - - portED - - - - - - - serverNameED - portED - descriptionED - usernameED - passwordED - PushButton3 - PushButton4 - - - - diff -Nru kdepim-4.12.97/libkleo/ui/dnattributeorderconfigwidget.cpp kdepim-4.13.0/libkleo/ui/dnattributeorderconfigwidget.cpp --- kdepim-4.12.97/libkleo/ui/dnattributeorderconfigwidget.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkleo/ui/dnattributeorderconfigwidget.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -129,13 +129,14 @@ int row, col; const char * tooltip; const char * slot; + bool autorepeat; } navButtons[] = { - { "go-top", 0, 1, I18N_NOOP( "Move to top" ), SLOT(slotDoubleUpButtonClicked()) }, - { "go-up", 1, 1, I18N_NOOP( "Move one up" ), SLOT(slotUpButtonClicked()) }, - { "go-previous", 2, 0, I18N_NOOP( "Remove from current attribute order" ), SLOT(slotLeftButtonClicked()) }, - { "go-next", 2, 2, I18N_NOOP( "Add to current attribute order" ), SLOT(slotRightButtonClicked()) }, - { "go-down", 3, 1, I18N_NOOP( "Move one down" ), SLOT(slotDownButtonClicked()) }, - { "go-bottom", 4, 1, I18N_NOOP( "Move to bottom" ), SLOT(slotDoubleDownButtonClicked()) } + { "go-top", 0, 1, I18N_NOOP( "Move to top" ), SLOT(slotDoubleUpButtonClicked()), false }, + { "go-up", 1, 1, I18N_NOOP( "Move one up" ), SLOT(slotUpButtonClicked()), true }, + { "go-previous", 2, 0, I18N_NOOP( "Remove from current attribute order" ), SLOT(slotLeftButtonClicked()), false }, + { "go-next", 2, 2, I18N_NOOP( "Add to current attribute order" ), SLOT(slotRightButtonClicked()), false }, + { "go-down", 3, 1, I18N_NOOP( "Move one down" ), SLOT(slotDownButtonClicked()), true }, + { "go-bottom", 4, 1, I18N_NOOP( "Move to bottom" ), SLOT(slotDoubleDownButtonClicked()), false } }; for ( unsigned int i = 0 ; i < sizeof navButtons / sizeof *navButtons ; ++i ) { @@ -144,6 +145,7 @@ tb->setEnabled( false ); tb->setToolTip( i18n( navButtons[i].tooltip ) ); xlay->addWidget( tb, navButtons[i].row, navButtons[i].col ); + tb->setAutoRepeat(navButtons[i].autorepeat); connect( tb, SIGNAL(clicked()), navButtons[i].slot ); } diff -Nru kdepim-4.12.97/libkleo/ui/filenamerequester.cpp kdepim-4.13.0/libkleo/ui/filenamerequester.cpp --- kdepim-4.12.97/libkleo/ui/filenamerequester.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkleo/ui/filenamerequester.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -64,7 +65,7 @@ QDir::Filters filter; #endif - QLineEdit lineedit; + KLineEdit lineedit; QToolButton button; QHBoxLayout hlay; @@ -98,7 +99,7 @@ #ifndef QT_NO_DIRMODEL lineedit.setCompleter( &completer ); #endif - + lineedit.setClearButtonShown(true); hlay.setMargin( 0 ); hlay.addWidget( &lineedit ); hlay.addWidget( &button ); diff -Nru kdepim-4.12.97/libkleo/ui/keyselectiondialog.cpp kdepim-4.13.0/libkleo/ui/keyselectiondialog.cpp --- kdepim-4.12.97/libkleo/ui/keyselectiondialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libkleo/ui/keyselectiondialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -482,6 +482,9 @@ KConfigGroup dialogConfig( KGlobal::config(), "Key Selection Dialog" ); dialogSize = dialogConfig.readEntry( "Dialog size", dialogSize ); + const QByteArray headerState = dialogConfig.readEntry( "header", QByteArray()); + if (!headerState.isEmpty()) + mKeyListView->header()->restoreState(headerState); resize( dialogSize ); } } @@ -489,6 +492,7 @@ Kleo::KeySelectionDialog::~KeySelectionDialog() { KConfigGroup dialogConfig( KGlobal::config(), "Key Selection Dialog" ); dialogConfig.writeEntry( "Dialog size", size() ); + dialogConfig.writeEntry( "header", mKeyListView->header()->saveState()); dialogConfig.sync(); } diff -Nru kdepim-4.12.97/libksieve/ksieveui/data/scripts/copy/template.desktop kdepim-4.13.0/libksieve/ksieveui/data/scripts/copy/template.desktop --- kdepim-4.12.97/libksieve/ksieveui/data/scripts/copy/template.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libksieve/ksieveui/data/scripts/copy/template.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -19,6 +19,7 @@ Name[pl]=Przenieś do katalogu Name[pt]=Mover para a pasta Name[pt_BR]=Mover para a pasta +Name[ru]=Перемещение в папку Name[sk]=Presunúť do adresára Name[sr]=Премести у фасциклу Name[sr@ijekavian]=Премести у фасциклу diff -Nru kdepim-4.12.97/libksieve/ksieveui/editor/sieveeditortabwidget.cpp kdepim-4.13.0/libksieve/ksieveui/editor/sieveeditortabwidget.cpp --- kdepim-4.12.97/libksieve/ksieveui/editor/sieveeditortabwidget.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libksieve/ksieveui/editor/sieveeditortabwidget.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -21,6 +21,7 @@ #include +#include #include using namespace KSieveUi; @@ -102,5 +103,6 @@ setTabBarHidden(false); } KTabWidget::tabInserted(index); + tabBar()->tabButton(0, QTabBar::RightSide)->setEnabled(false); } diff -Nru kdepim-4.12.97/libksieve/ksieveui/editor/sievetextedit.cpp kdepim-4.13.0/libksieve/ksieveui/editor/sievetextedit.cpp --- kdepim-4.12.97/libksieve/ksieveui/editor/sievetextedit.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libksieve/ksieveui/editor/sievetextedit.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -164,9 +164,9 @@ setTextCursor(tc); } -QString SieveTextEdit::selectedWord() const +QString SieveTextEdit::selectedWord(const QPoint &pos) const { - QTextCursor wordSelectCursor(textCursor()); + QTextCursor wordSelectCursor(pos.isNull() ? textCursor() : cursorForPosition(pos)); wordSelectCursor.clearSelection(); wordSelectCursor.select(QTextCursor::WordUnderCursor); const QString word = wordSelectCursor.selectedText(); @@ -237,10 +237,10 @@ setCompleterList(completerList() + capabilities); } -void SieveTextEdit::addExtraMenuEntry(QMenu *menu) +void SieveTextEdit::addExtraMenuEntry(QMenu *menu, const QPoint &pos) { if (!textCursor().hasSelection()) { - const QString word = selectedWord(); + const QString word = selectedWord(pos); const KSieveUi::SieveEditorUtil::HelpVariableName type = KSieveUi::SieveEditorUtil::strToVariableName(word); if (type != KSieveUi::SieveEditorUtil::UnknownHelp) { QAction *separator = new QAction(menu); diff -Nru kdepim-4.12.97/libksieve/ksieveui/editor/sievetextedit.h kdepim-4.13.0/libksieve/ksieveui/editor/sievetextedit.h --- kdepim-4.12.97/libksieve/ksieveui/editor/sievetextedit.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libksieve/ksieveui/editor/sievetextedit.h 2014-04-10 07:40:20.000000000 +0000 @@ -58,7 +58,7 @@ void initCompleter(); void keyPressEvent(QKeyEvent* e); void resizeEvent(QResizeEvent *event); - void addExtraMenuEntry(QMenu *menu); + void addExtraMenuEntry(QMenu *menu, const QPoint &pos); Q_SIGNALS: void openHelp(const QString &variableName, const QString &url); @@ -66,7 +66,7 @@ private: QStringList completerList() const; void setCompleterList(const QStringList &list); - QString selectedWord() const; + QString selectedWord(const QPoint &pos = QPoint()) const; QCompleter *m_completer; SieveLineNumberArea *m_sieveLineNumberArea; diff -Nru kdepim-4.12.97/libksieve/ksieveui/vacation/vacationpagewidget.cpp kdepim-4.13.0/libksieve/ksieveui/vacation/vacationpagewidget.cpp --- kdepim-4.12.97/libksieve/ksieveui/vacation/vacationpagewidget.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/libksieve/ksieveui/vacation/vacationpagewidget.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -67,9 +67,10 @@ "office replies for you." "Please contact your system administrator." ) ); vbox->addWidget(lab); + vbox->setAlignment(lab, Qt::AlignVCenter); + lab->setWordWrap(true); w->setLayout(vbox); - vbox->addStretch(); mStackWidget->addWidget(w); mStackWidget->setCurrentIndex(Script); diff -Nru kdepim-4.12.97/mailcommon/mdn/sendmdnhandler.cpp kdepim-4.13.0/mailcommon/mdn/sendmdnhandler.cpp --- kdepim-4.12.97/mailcommon/mdn/sendmdnhandler.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/mailcommon/mdn/sendmdnhandler.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -41,9 +41,9 @@ class SendMdnHandler::Private { - public: +public: Private( SendMdnHandler *qq, IKernel *kernel ) - : q( qq ), mKernel( kernel ) + : q( qq ), mKernel( kernel ) { } @@ -57,83 +57,83 @@ void SendMdnHandler::Private::handleMessages() { - while ( !mItemQueue.isEmpty() ) { - Akonadi::Item item = mItemQueue.dequeue(); + while ( !mItemQueue.isEmpty() ) { + Akonadi::Item item = mItemQueue.dequeue(); #if 0 - // should we send an MDN? - if ( MessageViewer::GlobalSettings::notSendWhenEncrypted() && - message()->encryptionState() != KMMsgNotEncrypted && - message()->encryptionState() != KMMsgEncryptionStateUnknown ) { - return; - } + // should we send an MDN? + if ( MessageViewer::GlobalSettings::notSendWhenEncrypted() && + message()->encryptionState() != KMMsgNotEncrypted && + message()->encryptionState() != KMMsgEncryptionStateUnknown ) { + return; + } #else - kDebug() << "AKONADI PORT: Disabled code in " << Q_FUNC_INFO; + kDebug() << "AKONADI PORT: Disabled code in " << Q_FUNC_INFO; #endif - const Akonadi::Collection collection = item.parentCollection(); - if ( collection.isValid() && - ( CommonKernel->folderIsSentMailFolder( collection ) || - CommonKernel->folderIsTrash( collection ) || - CommonKernel->folderIsDraftOrOutbox( collection ) || - CommonKernel->folderIsTemplates( collection ) ) ) { - continue; - } + const Akonadi::Collection collection = item.parentCollection(); + if ( collection.isValid() && + ( CommonKernel->folderIsSentMailFolder( collection ) || + CommonKernel->folderIsTrash( collection ) || + CommonKernel->folderIsDraftOrOutbox( collection ) || + CommonKernel->folderIsTemplates( collection ) ) ) { + continue; + } - const KMime::Message::Ptr message = MessageCore::Util::message( item ); - if ( !message ) { - continue; - } + const KMime::Message::Ptr message = MessageCore::Util::message( item ); + if ( !message ) { + continue; + } - const QPair mdnSend = - MDNAdviceHelper::instance()->checkAndSetMDNInfo( item, KMime::MDN::Displayed ); - if ( mdnSend.first ) { - const int quote = MessageViewer::GlobalSettings::self()->quoteMessage(); - - MessageComposer::MessageFactory factory( message, Akonadi::Item().id() ); - factory.setIdentityManager( mKernel->identityManager() ); - factory.setFolderIdentity( MailCommon::Util::folderIdentity( item ) ); - - const KMime::Message::Ptr mdn = - factory.createMDN( KMime::MDN::ManualAction, KMime::MDN::Displayed, mdnSend.second, quote ); - if ( mdn ) { - if ( !mKernel->msgSender()->send( mdn ) ) { - kDebug() << "Sending failed."; + const QPair mdnSend = + MDNAdviceHelper::instance()->checkAndSetMDNInfo( item, KMime::MDN::Displayed ); + if ( mdnSend.first ) { + const int quote = MessageViewer::GlobalSettings::self()->quoteMessage(); + + MessageComposer::MessageFactory factory( message, Akonadi::Item().id() ); + factory.setIdentityManager( mKernel->identityManager() ); + factory.setFolderIdentity( MailCommon::Util::folderIdentity( item ) ); + + const KMime::Message::Ptr mdn = + factory.createMDN( KMime::MDN::ManualAction, KMime::MDN::Displayed, mdnSend.second, quote ); + if ( mdn ) { + if ( !mKernel->msgSender()->send( mdn ) ) { + kDebug() << "Sending failed."; + } + } } - } } - } } SendMdnHandler::SendMdnHandler( IKernel *kernel, QObject *parent ) - : QObject( parent ), d( new Private( this, kernel ) ) + : QObject( parent ), d( new Private( this, kernel ) ) { - d->mTimer.setSingleShot( true ); - connect( &d->mTimer, SIGNAL(timeout()), this, SLOT(handleMessages()) ); + d->mTimer.setSingleShot( true ); + connect( &d->mTimer, SIGNAL(timeout()), this, SLOT(handleMessages()) ); } SendMdnHandler::~SendMdnHandler() { - delete d; + delete d; } void SendMdnHandler::setItem( const Akonadi::Item &item ) { - if ( item.hasFlag( Akonadi::MessageFlags::Seen ) ) { - return; - } + if ( item.hasFlag( Akonadi::MessageFlags::Seen ) ) { + return; + } - d->mTimer.stop(); + d->mTimer.stop(); - d->mItemQueue.enqueue( item ); + d->mItemQueue.enqueue( item ); - if ( MessageViewer::GlobalSettings::self()->delayedMarkAsRead() && - MessageViewer::GlobalSettings::self()->delayedMarkTime() != 0 ) { - d->mTimer.start( MessageViewer::GlobalSettings::self()->delayedMarkTime() * 1000 ); - return; - } + if ( MessageViewer::GlobalSettings::self()->delayedMarkAsRead() && + MessageViewer::GlobalSettings::self()->delayedMarkTime() != 0 ) { + d->mTimer.start( MessageViewer::GlobalSettings::self()->delayedMarkTime() * 1000 ); + return; + } - d->handleMessages(); + d->handleMessages(); } #include "moc_sendmdnhandler.cpp" diff -Nru kdepim-4.12.97/messagecomposer/composer/kmeditor.cpp kdepim-4.13.0/messagecomposer/composer/kmeditor.cpp --- kdepim-4.12.97/messagecomposer/composer/kmeditor.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagecomposer/composer/kmeditor.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -252,18 +252,23 @@ if(d->mAutoCorrection && !isLineQuoted(textCursor().block().text())) { const QTextCharFormat initialTextFormat = textCursor().charFormat(); const bool richText = (textMode() == KRichTextEdit::Rich); - d->mAutoCorrection->autocorrect(richText, *document(),textCursor().position()); + int position = textCursor().position(); + d->mAutoCorrection->autocorrect(richText, *document(), position); + QTextCursor cur = textCursor(); + cur.setPosition(position); if (e->key() == Qt::Key_Space) { if (richText && !isSpecial(initialTextFormat)) - textCursor().insertText(QLatin1String(" "), initialTextFormat); + cur.insertText(QLatin1String(" "), initialTextFormat); else - textCursor().insertText(QLatin1String(" ")); + cur.insertText(QLatin1String(" ")); + setTextCursor(cur); return; } else { if (richText && !isSpecial(initialTextFormat)) - textCursor().insertText(QLatin1String("\n"), initialTextFormat); + cur.insertText(QLatin1String("\n"), initialTextFormat); else - textCursor().insertText(QLatin1String("\n")); + cur.insertText(QLatin1String("\n")); + setTextCursor(cur); return; } } diff -Nru kdepim-4.12.97/messagecomposer/recipient/recipientseditor.cpp kdepim-4.13.0/messagecomposer/recipient/recipientseditor.cpp --- kdepim-4.12.97/messagecomposer/recipient/recipientseditor.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagecomposer/recipient/recipientseditor.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -71,8 +71,8 @@ layout()->addWidget( mSideWidget ); - connect( mSideWidget, SIGNAL(pickedRecipient(Recipient)), - SLOT(slotPickedRecipient(Recipient)) ); + connect( mSideWidget, SIGNAL(pickedRecipient(Recipient,bool&)), + SLOT(slotPickedRecipient(Recipient,bool&)) ); connect( mSideWidget, SIGNAL(saveDistributionList()), SLOT(saveDistributionList()) ); @@ -89,9 +89,9 @@ { } -void RecipientsEditor::addRecipient( const QString& recipient, Recipient::Type type ) +bool RecipientsEditor::addRecipient( const QString& recipient, Recipient::Type type ) { - addData( Recipient::Ptr( new Recipient ( recipient, type ) ) ); + return addData( Recipient::Ptr( new Recipient ( recipient, type ) ) ); } void RecipientsEditor::setRecipientString( const QList< KMime::Types::Mailbox >& mailboxes, Recipient::Type type ) @@ -191,10 +191,10 @@ } } -void MessageComposer::RecipientsEditor::slotPickedRecipient( const Recipient& rec ) +void MessageComposer::RecipientsEditor::slotPickedRecipient( const Recipient& rec, bool &tooManyAddress ) { Recipient::Type t = rec.type(); - addRecipient( rec.email(), t == Recipient::Undefined ? Recipient::To : t ); + tooManyAddress = addRecipient( rec.email(), t == Recipient::Undefined ? Recipient::To : t ); mModified = true; } diff -Nru kdepim-4.12.97/messagecomposer/recipient/recipientseditor.h kdepim-4.13.0/messagecomposer/recipient/recipientseditor.h --- kdepim-4.12.97/messagecomposer/recipient/recipientseditor.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagecomposer/recipient/recipientseditor.h 2014-04-10 07:40:20.000000000 +0000 @@ -70,7 +70,7 @@ @param recipient The recipient(s) you want to add. @param type The recipient type. */ - void addRecipient( const QString & recipient, Recipient::Type type ); + bool addRecipient( const QString & recipient, Recipient::Type type ); /** Removes the recipient provided it can be found and has the given type. @param recipient The recipient(s) you want to remove. @@ -88,7 +88,7 @@ void saveDistributionList(); protected slots: - void slotPickedRecipient( const Recipient & ); + void slotPickedRecipient(const Recipient & , bool &tooManyAddress); void slotLineAdded( KPIM::MultiplyingLine* ); void slotLineDeleted( int pos ); void slotCalculateTotal(); diff -Nru kdepim-4.12.97/messagecomposer/recipient/recipientseditorsidewidget.cpp kdepim-4.13.0/messagecomposer/recipient/recipientseditorsidewidget.cpp --- kdepim-4.12.97/messagecomposer/recipient/recipientseditorsidewidget.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagecomposer/recipient/recipientseditorsidewidget.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -81,8 +81,8 @@ // hacks to allow picker() to be const in the presence of lazy loading RecipientsEditorSideWidget *non_const_this = const_cast( this ); mRecipientPicker = new RecipientsPicker( non_const_this ); - connect( mRecipientPicker, SIGNAL(pickedRecipient(Recipient)), - non_const_this, SIGNAL(pickedRecipient(Recipient)) ); + connect( mRecipientPicker, SIGNAL(pickedRecipient(Recipient,bool&)), + non_const_this, SIGNAL(pickedRecipient(Recipient,bool&)) ); mPickerPositioner = new KWindowPositioner( mSelectButton, mRecipientPicker ); } return mRecipientPicker; diff -Nru kdepim-4.12.97/messagecomposer/recipient/recipientseditorsidewidget.h kdepim-4.13.0/messagecomposer/recipient/recipientseditorsidewidget.h --- kdepim-4.12.97/messagecomposer/recipient/recipientseditorsidewidget.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagecomposer/recipient/recipientseditorsidewidget.h 2014-04-10 07:40:20.000000000 +0000 @@ -51,7 +51,7 @@ void pickRecipient(); signals: - void pickedRecipient( const Recipient & ); + void pickedRecipient( const Recipient &, bool & ); void saveDistributionList(); private: diff -Nru kdepim-4.12.97/messagecomposer/recipient/recipientspicker.cpp kdepim-4.13.0/messagecomposer/recipient/recipientspicker.cpp --- kdepim-4.12.97/messagecomposer/recipient/recipientspicker.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagecomposer/recipient/recipientspicker.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -157,12 +157,15 @@ return; } + bool tooManyAddress = false; foreach ( const Akonadi::EmailAddressSelection &selection, selections ) { Recipient recipient; recipient.setType( type ); recipient.setEmail( selection.quotedEmail() ); - emit pickedRecipient( recipient ); + emit pickedRecipient( recipient, tooManyAddress ); + if (tooManyAddress) + break; } } @@ -207,7 +210,10 @@ { const KABC::Addressee::List contacts = mLdapSearchDialog->selectedContacts(); foreach ( const KABC::Addressee &contact, contacts ) { - emit pickedRecipient( Recipient( contact.fullEmail(), Recipient::Undefined ) ); + bool tooManyAddress = false; + emit pickedRecipient( Recipient( contact.fullEmail(), Recipient::Undefined ), tooManyAddress ); + if (tooManyAddress) + break; } } diff -Nru kdepim-4.12.97/messagecomposer/recipient/recipientspicker.h kdepim-4.13.0/messagecomposer/recipient/recipientspicker.h --- kdepim-4.12.97/messagecomposer/recipient/recipientspicker.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagecomposer/recipient/recipientspicker.h 2014-04-10 07:40:20.000000000 +0000 @@ -50,7 +50,7 @@ void setDefaultType( Recipient::Type ); Q_SIGNALS: - void pickedRecipient( const Recipient & ); + void pickedRecipient( const Recipient &, bool & ); protected: void readConfig(); diff -Nru kdepim-4.12.97/messagecore/CMakeLists.txt kdepim-4.13.0/messagecore/CMakeLists.txt --- kdepim-4.12.97/messagecore/CMakeLists.txt 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagecore/CMakeLists.txt 2014-04-10 07:40:20.000000000 +0000 @@ -1,3 +1,4 @@ +project(messagecore) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}" ) add_definitions( -DQT_NO_CAST_FROM_ASCII ) add_definitions( -DQT_NO_CAST_TO_ASCII ) diff -Nru kdepim-4.12.97/messagecore/tests/stringutiltest.cpp kdepim-4.13.0/messagecore/tests/stringutiltest.cpp --- kdepim-4.12.97/messagecore/tests/stringutiltest.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagecore/tests/stringutiltest.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -343,9 +343,11 @@ QVERIFY( StringUtil::isCryptoPart( QLatin1String("application"), QLatin1String("pkcs7-signature"), QString() ) ); QVERIFY( StringUtil::isCryptoPart( QLatin1String("application"), QLatin1String("x-pkcs7-signature"), QString() ) ); QVERIFY( StringUtil::isCryptoPart( QLatin1String("application"), QLatin1String("octet-stream"), QLatin1String("msg.asc") ) ); + QVERIFY( StringUtil::isCryptoPart( QLatin1String("application"), QLatin1String("octet-stream"), QLatin1String("encrypted.asc") ) ); QVERIFY( !StringUtil::isCryptoPart( QLatin1String("application"), QLatin1String("octet-stream"), QLatin1String("bla.foo") ) ); QVERIFY( !StringUtil::isCryptoPart( QLatin1String("application"), QLatin1String("foo"), QString() ) ); QVERIFY( !StringUtil::isCryptoPart( QLatin1String("application"), QLatin1String("foo"), QLatin1String("msg.asc") ) ); + QVERIFY( !StringUtil::isCryptoPart( QLatin1String("application"), QLatin1String("foo"), QLatin1String("encrypted.asc") ) ); } void StringUtilTest::test_stripOffMessagePrefix() diff -Nru kdepim-4.12.97/messagecore/utils/stringutil.cpp kdepim-4.13.0/messagecore/utils/stringutil.cpp --- kdepim-4.12.97/messagecore/utils/stringutil.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagecore/utils/stringutil.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -938,7 +938,8 @@ subTypeLower == QLatin1String( "pkcs7-signature" ) || subTypeLower == QLatin1String( "x-pkcs7-signature" ) || ( subTypeLower == QLatin1String( "octet-stream" ) && - fileName.toLower() == QLatin1String( "msg.asc" ) ) ) ); + ( fileName.toLower() == QLatin1String( "msg.asc" ) || + fileName.toLower() == QLatin1String( "encrypted.asc" ) ) ) ) ); } QString formatString( const QString &wildString, const QString &fromAddr ) diff -Nru kdepim-4.12.97/messagecore/widgets/annotationdialog.cpp kdepim-4.13.0/messagecore/widgets/annotationdialog.cpp --- kdepim-4.12.97/messagecore/widgets/annotationdialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagecore/widgets/annotationdialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -91,6 +91,7 @@ if ( button == KDialog::Ok ) { bool textIsEmpty = d->mTextEdit->toPlainText().isEmpty(); if ( !textIsEmpty ) { + d->mItem.removeAttribute(); Akonadi::EntityAnnotationsAttribute *annotation = d->mItem.attribute(Akonadi::Entity::AddIfMissing); annotation->insert("/private/comment", d->mTextEdit->toPlainText()); d->mItem.addAttribute(annotation); diff -Nru kdepim-4.12.97/messagelist/core/aggregation.cpp kdepim-4.13.0/messagelist/core/aggregation.cpp --- kdepim-4.12.97/messagelist/core/aggregation.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/aggregation.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -30,242 +30,242 @@ Aggregation::Aggregation( - const QString &name, - const QString &description, - Grouping grouping, - GroupExpandPolicy groupExpandPolicy, - Threading threading, - ThreadLeader threadLeader, - ThreadExpandPolicy threadExpandPolicy, - FillViewStrategy fillViewStrategy, bool readOnly - ) - : OptionSet( name, description, readOnly ), - mGrouping( grouping ), - mGroupExpandPolicy( groupExpandPolicy ), - mThreading( threading ), - mThreadLeader( threadLeader ), - mThreadExpandPolicy( threadExpandPolicy ), - mFillViewStrategy( fillViewStrategy ) + const QString &name, + const QString &description, + Grouping grouping, + GroupExpandPolicy groupExpandPolicy, + Threading threading, + ThreadLeader threadLeader, + ThreadExpandPolicy threadExpandPolicy, + FillViewStrategy fillViewStrategy, bool readOnly + ) + : OptionSet( name, description, readOnly ), + mGrouping( grouping ), + mGroupExpandPolicy( groupExpandPolicy ), + mThreading( threading ), + mThreadLeader( threadLeader ), + mThreadExpandPolicy( threadExpandPolicy ), + mFillViewStrategy( fillViewStrategy ) { } Aggregation::Aggregation( - const Aggregation &opt - ) - : OptionSet( opt ), - mGrouping( opt.mGrouping ), - mGroupExpandPolicy( opt.mGroupExpandPolicy ), - mThreading( opt.mThreading ), - mThreadLeader( opt.mThreadLeader ), - mThreadExpandPolicy( opt.mThreadExpandPolicy ), - mFillViewStrategy( opt.mFillViewStrategy ) + const Aggregation &opt + ) + : OptionSet( opt ), + mGrouping( opt.mGrouping ), + mGroupExpandPolicy( opt.mGroupExpandPolicy ), + mThreading( opt.mThreading ), + mThreadLeader( opt.mThreadLeader ), + mThreadExpandPolicy( opt.mThreadExpandPolicy ), + mFillViewStrategy( opt.mFillViewStrategy ) { } Aggregation::Aggregation() - : OptionSet(), - mGrouping( NoGrouping ), - mGroupExpandPolicy( NeverExpandGroups ), - mThreading( NoThreading ), - mThreadLeader( TopmostMessage ), - mThreadExpandPolicy( NeverExpandThreads ), - mFillViewStrategy( FavorInteractivity ) + : OptionSet(), + mGrouping( NoGrouping ), + mGroupExpandPolicy( NeverExpandGroups ), + mThreading( NoThreading ), + mThreadLeader( TopmostMessage ), + mThreadExpandPolicy( NeverExpandThreads ), + mFillViewStrategy( FavorInteractivity ) { } bool Aggregation::load( QDataStream &stream ) { - int val; + int val; - stream >> val; - if ( val != gAggregationCurrentVersion ) - return false; // b0rken (invalid version) - - stream >> val; - mGrouping = (Grouping)val; - switch( mGrouping ) - { + stream >> val; + if ( val != gAggregationCurrentVersion ) + return false; // b0rken (invalid version) + + stream >> val; + mGrouping = (Grouping)val; + switch( mGrouping ) + { case NoGrouping: case GroupByDate: case GroupByDateRange: case GroupBySenderOrReceiver: case GroupBySender: case GroupByReceiver: - // ok - break; + // ok + break; default: - // b0rken - return false; - break; - } - - stream >> val; // Formerly contained group sorting - stream >> val; // Formerly contained group sorting direction - - stream >> val; - mGroupExpandPolicy = (GroupExpandPolicy)val; - switch( mGroupExpandPolicy ) - { + // b0rken + return false; + break; + } + + stream >> val; // Formerly contained group sorting + stream >> val; // Formerly contained group sorting direction + + stream >> val; + mGroupExpandPolicy = (GroupExpandPolicy)val; + switch( mGroupExpandPolicy ) + { case NeverExpandGroups: case ExpandRecentGroups: case AlwaysExpandGroups: - // ok - break; + // ok + break; default: - // b0rken - return false; - break; - } - - stream >> val; - mThreading = (Threading)val; - switch( mThreading ) - { + // b0rken + return false; + break; + } + + stream >> val; + mThreading = (Threading)val; + switch( mThreading ) + { case NoThreading: case PerfectOnly: case PerfectAndReferences: case PerfectReferencesAndSubject: - // ok - break; + // ok + break; default: - // b0rken - return false; - break; - } - - stream >> val; - mThreadLeader = (ThreadLeader)val; - switch( mThreadLeader ) - { + // b0rken + return false; + break; + } + + stream >> val; + mThreadLeader = (ThreadLeader)val; + switch( mThreadLeader ) + { case MostRecentMessage: case TopmostMessage: - // ok - // FIXME: Should check that thread leaders setting matches grouping and threading settings. - break; - default: - // b0rken - return false; - break; - } - - stream >> val; - mThreadExpandPolicy = (ThreadExpandPolicy)val; - switch( mThreadExpandPolicy ) - { + // ok + // FIXME: Should check that thread leaders setting matches grouping and threading settings. + break; + default: + // b0rken + return false; + break; + } + + stream >> val; + mThreadExpandPolicy = (ThreadExpandPolicy)val; + switch( mThreadExpandPolicy ) + { case NeverExpandThreads: case ExpandThreadsWithNewMessages: case ExpandThreadsWithUnreadMessages: case ExpandThreadsWithUnreadOrImportantMessages: case AlwaysExpandThreads: - // ok - break; + // ok + break; default: - // b0rken - return false; - break; - } - - stream >> val; // Formely contained message sorting - stream >> val; // Formely contained message sort direction - - stream >> val; - mFillViewStrategy = (FillViewStrategy)val; - switch( mFillViewStrategy ) - { + // b0rken + return false; + break; + } + + stream >> val; // Formely contained message sorting + stream >> val; // Formely contained message sort direction + + stream >> val; + mFillViewStrategy = (FillViewStrategy)val; + switch( mFillViewStrategy ) + { case FavorSpeed: case FavorInteractivity: case BatchNoInteractivity: - // ok - break; + // ok + break; default: - // b0rken - return false; - break; - } + // b0rken + return false; + break; + } - return true; + return true; } void Aggregation::save( QDataStream &stream ) const { - stream << (int)gAggregationCurrentVersion; - stream << (int)mGrouping; - stream << 0; // Formerly group sorting - stream << 0; // Formerly group sort direction - stream << (int)mGroupExpandPolicy; - stream << (int)mThreading; - stream << (int)mThreadLeader; - stream << (int)mThreadExpandPolicy; - stream << 0; // Formerly message sorting - stream << 0; // Formerly message sort direction - stream << (int)mFillViewStrategy; + stream << (int)gAggregationCurrentVersion; + stream << (int)mGrouping; + stream << 0; // Formerly group sorting + stream << 0; // Formerly group sort direction + stream << (int)mGroupExpandPolicy; + stream << (int)mThreading; + stream << (int)mThreadLeader; + stream << (int)mThreadExpandPolicy; + stream << 0; // Formerly message sorting + stream << 0; // Formerly message sort direction + stream << (int)mFillViewStrategy; } QList< QPair< QString, int > > Aggregation::enumerateGroupingOptions() { - QList< QPair< QString, int > > ret; - ret.append( QPair< QString, int >( i18nc( "No grouping of messages", "None" ), NoGrouping ) ); - ret.append( QPair< QString, int >( i18n( "By Exact Date (of Thread Leaders)" ), GroupByDate ) ); - ret.append( QPair< QString, int >( i18n( "By Smart Date Ranges (of Thread Leaders)" ), GroupByDateRange ) ); - ret.append( QPair< QString, int >( i18n( "By Smart Sender/Receiver" ), GroupBySenderOrReceiver ) ); - ret.append( QPair< QString, int >( i18n( "By Sender" ), GroupBySender ) ); - ret.append( QPair< QString, int >( i18n( "By Receiver" ), GroupByReceiver ) ); - return ret; + QList< QPair< QString, int > > ret; + ret.append( QPair< QString, int >( i18nc( "No grouping of messages", "None" ), NoGrouping ) ); + ret.append( QPair< QString, int >( i18n( "By Exact Date (of Thread Leaders)" ), GroupByDate ) ); + ret.append( QPair< QString, int >( i18n( "By Smart Date Ranges (of Thread Leaders)" ), GroupByDateRange ) ); + ret.append( QPair< QString, int >( i18n( "By Smart Sender/Receiver" ), GroupBySenderOrReceiver ) ); + ret.append( QPair< QString, int >( i18n( "By Sender" ), GroupBySender ) ); + ret.append( QPair< QString, int >( i18n( "By Receiver" ), GroupByReceiver ) ); + return ret; } QList< QPair< QString, int > > Aggregation::enumerateGroupExpandPolicyOptions( Grouping g ) { - QList< QPair< QString, int > > ret; - if ( g == NoGrouping ) + QList< QPair< QString, int > > ret; + if ( g == NoGrouping ) + return ret; + ret.append( QPair< QString, int >( i18n( "Never Expand Groups" ), NeverExpandGroups ) ); + if ( ( g == GroupByDate ) || ( g == GroupByDateRange ) ) + ret.append( QPair< QString, int >( i18n( "Expand Recent Groups" ), ExpandRecentGroups ) ); + ret.append( QPair< QString, int >( i18n( "Always Expand Groups" ), AlwaysExpandGroups ) ); return ret; - ret.append( QPair< QString, int >( i18n( "Never Expand Groups" ), NeverExpandGroups ) ); - if ( ( g == GroupByDate ) || ( g == GroupByDateRange ) ) - ret.append( QPair< QString, int >( i18n( "Expand Recent Groups" ), ExpandRecentGroups ) ); - ret.append( QPair< QString, int >( i18n( "Always Expand Groups" ), AlwaysExpandGroups ) ); - return ret; } QList< QPair< QString, int > > Aggregation::enumerateThreadingOptions() { - QList< QPair< QString, int > > ret; - ret.append( QPair< QString, int >( i18nc( "No threading of messages", "None" ), NoThreading ) ); - ret.append( QPair< QString, int >( i18n( "Perfect Only" ), PerfectOnly ) ); - ret.append( QPair< QString, int >( i18n( "Perfect and by References" ), PerfectAndReferences ) ); - ret.append( QPair< QString, int >( i18n( "Perfect, by References and by Subject" ), PerfectReferencesAndSubject ) ); - return ret; + QList< QPair< QString, int > > ret; + ret.append( QPair< QString, int >( i18nc( "No threading of messages", "None" ), NoThreading ) ); + ret.append( QPair< QString, int >( i18n( "Perfect Only" ), PerfectOnly ) ); + ret.append( QPair< QString, int >( i18n( "Perfect and by References" ), PerfectAndReferences ) ); + ret.append( QPair< QString, int >( i18n( "Perfect, by References and by Subject" ), PerfectReferencesAndSubject ) ); + return ret; } QList< QPair< QString, int > > Aggregation::enumerateThreadLeaderOptions( Grouping g, Threading t ) { - QList< QPair< QString, int > > ret; - if ( t == NoThreading ) + QList< QPair< QString, int > > ret; + if ( t == NoThreading ) + return ret; + ret.append( QPair< QString, int >( i18n( "Topmost Message" ), TopmostMessage ) ); + if ( ( g != GroupByDate ) && ( g != GroupByDateRange ) ) + return ret; + ret.append( QPair< QString, int >( i18n( "Most Recent Message" ), MostRecentMessage ) ); return ret; - ret.append( QPair< QString, int >( i18n( "Topmost Message" ), TopmostMessage ) ); - if ( ( g != GroupByDate ) && ( g != GroupByDateRange ) ) - return ret; - ret.append( QPair< QString, int >( i18n( "Most Recent Message" ), MostRecentMessage ) ); - return ret; } QList< QPair< QString, int > > Aggregation::enumerateThreadExpandPolicyOptions( Threading t ) { - QList< QPair< QString, int > > ret; - if ( t == NoThreading ) + QList< QPair< QString, int > > ret; + if ( t == NoThreading ) + return ret; + ret.append( QPair< QString, int >( i18n( "Never Expand Threads" ), NeverExpandThreads ) ); + ret.append( QPair< QString, int >( i18n( "Expand Threads With Unread Messages" ), ExpandThreadsWithUnreadMessages ) ); + ret.append( QPair< QString, int >( i18n( "Expand Threads With Unread or Important Messages" ), ExpandThreadsWithUnreadOrImportantMessages ) ); + ret.append( QPair< QString, int >( i18n( "Always Expand Threads" ), AlwaysExpandThreads ) ); return ret; - ret.append( QPair< QString, int >( i18n( "Never Expand Threads" ), NeverExpandThreads ) ); - ret.append( QPair< QString, int >( i18n( "Expand Threads With Unread Messages" ), ExpandThreadsWithUnreadMessages ) ); - ret.append( QPair< QString, int >( i18n( "Expand Threads With Unread or Important Messages" ), ExpandThreadsWithUnreadOrImportantMessages ) ); - ret.append( QPair< QString, int >( i18n( "Always Expand Threads" ), AlwaysExpandThreads ) ); - return ret; } QList< QPair< QString, int > > Aggregation::enumerateFillViewStrategyOptions() { - QList< QPair< QString, int > > ret; - ret.append( QPair< QString, int >( i18n( "Favor Interactivity" ), FavorInteractivity ) ); - ret.append( QPair< QString, int >( i18n( "Favor Speed" ), FavorSpeed ) ); - ret.append( QPair< QString, int >( i18n( "Batch Job (No Interactivity)" ), BatchNoInteractivity ) ); - return ret; + QList< QPair< QString, int > > ret; + ret.append( QPair< QString, int >( i18n( "Favor Interactivity" ), FavorInteractivity ) ); + ret.append( QPair< QString, int >( i18n( "Favor Speed" ), FavorSpeed ) ); + ret.append( QPair< QString, int >( i18n( "Batch Job (No Interactivity)" ), BatchNoInteractivity ) ); + return ret; } diff -Nru kdepim-4.12.97/messagelist/core/aggregation.h kdepim-4.13.0/messagelist/core/aggregation.h --- kdepim-4.12.97/messagelist/core/aggregation.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/aggregation.h 2014-04-10 07:40:20.000000000 +0000 @@ -44,250 +44,250 @@ { public: - /** + /** * Message grouping. * If you add values here please look at the implementations of the enumerate* functions * and add appropriate descriptors. */ - enum Grouping - { - NoGrouping, ///< Don't group messages at all - GroupByDate, ///< Group the messages by the date of the thread leader - GroupByDateRange, ///< Use smart (thread leader) date ranges ("Today","Yesterday","Last Week"...) - GroupBySenderOrReceiver, ///< Group by sender (incoming) or receiver (outgoing) field - GroupBySender, ///< Group by sender, always - GroupByReceiver ///< Group by receiver, always - // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) - // TODO: Group by message status: "Important messages", "Urgent messages", "To reply", "To do" etc... - // TODO: Group by message unread status: "Unread messages", "Read messages" (maybe "New" ?) - }; + enum Grouping + { + NoGrouping, ///< Don't group messages at all + GroupByDate, ///< Group the messages by the date of the thread leader + GroupByDateRange, ///< Use smart (thread leader) date ranges ("Today","Yesterday","Last Week"...) + GroupBySenderOrReceiver, ///< Group by sender (incoming) or receiver (outgoing) field + GroupBySender, ///< Group by sender, always + GroupByReceiver ///< Group by receiver, always + // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) + // TODO: Group by message status: "Important messages", "Urgent messages", "To reply", "To do" etc... + // TODO: Group by message unread status: "Unread messages", "Read messages" (maybe "New" ?) + }; - /** + /** * The available group expand policies. * If you add values here please look at the implementations of the enumerate* functions * and add appropriate descriptors. */ - enum GroupExpandPolicy - { - NeverExpandGroups, ///< Never expand groups during a view fill algorithm - ExpandRecentGroups, ///< Makes sense only with GroupByDate or GroupByDateRange - AlwaysExpandGroups ///< All groups are expanded as they are inserted - // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) - }; + enum GroupExpandPolicy + { + NeverExpandGroups, ///< Never expand groups during a view fill algorithm + ExpandRecentGroups, ///< Makes sense only with GroupByDate or GroupByDateRange + AlwaysExpandGroups ///< All groups are expanded as they are inserted + // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) + }; - /** + /** * The available threading methods. * If you add values here please look at the implementations of the enumerate* functions * and add appropriate descriptors. */ - enum Threading - { - NoThreading, ///< Perform no threading at all - PerfectOnly, ///< Thread by "In-Reply-To" field only - PerfectAndReferences, ///< Thread by "In-Reply-To" and "References" fields - PerfectReferencesAndSubject ///< Thread by all of the above and try to match subjects too - // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) - }; + enum Threading + { + NoThreading, ///< Perform no threading at all + PerfectOnly, ///< Thread by "In-Reply-To" field only + PerfectAndReferences, ///< Thread by "In-Reply-To" and "References" fields + PerfectReferencesAndSubject ///< Thread by all of the above and try to match subjects too + // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) + }; - /** + /** * The available thread leading options. Meaningless when threading is set to NoThreading. * If you add values here please look at the implementations of the enumerate* functions * and add appropriate descriptors. */ - enum ThreadLeader - { - TopmostMessage, ///< The thread grouping is computed from the topmost message (very similar to least recent, but might be different if timezones or machine clocks are screwed) - MostRecentMessage ///< The thread grouping is computed from the most recent message - // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) - }; + enum ThreadLeader + { + TopmostMessage, ///< The thread grouping is computed from the topmost message (very similar to least recent, but might be different if timezones or machine clocks are screwed) + MostRecentMessage ///< The thread grouping is computed from the most recent message + // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) + }; - /** + /** * The available thread expand policies. Meaningless when threading is set to NoThreading. * If you add values here please look at the implementations of the enumerate* functions * and add appropriate descriptors. */ - enum ThreadExpandPolicy - { - NeverExpandThreads, ///< Never expand any thread, this is fast - ExpandThreadsWithNewMessages, ///< DEPRECATED. New message status no longer exists. - ExpandThreadsWithUnreadMessages, ///< Expand threads with unread messages (this includes new) - AlwaysExpandThreads, ///< Expand all threads (this might be very slow) - ExpandThreadsWithUnreadOrImportantMessages ///< Expand threads with "hot" messages (this includes new, unread, important, todo) - // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) - }; + enum ThreadExpandPolicy + { + NeverExpandThreads, ///< Never expand any thread, this is fast + ExpandThreadsWithNewMessages, ///< DEPRECATED. New message status no longer exists. + ExpandThreadsWithUnreadMessages, ///< Expand threads with unread messages (this includes new) + AlwaysExpandThreads, ///< Expand all threads (this might be very slow) + ExpandThreadsWithUnreadOrImportantMessages ///< Expand threads with "hot" messages (this includes new, unread, important, todo) + // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) + }; - /** + /** * The available fill view strategies. * If you add values here please look at the implementations of the enumerate* functions * and add appropriate descriptors. */ - enum FillViewStrategy - { - FavorInteractivity, ///< Do small chunks of work, small intervals between chunks to allow for UI event processing - FavorSpeed, ///< Do larger chunks of work, zero intervals between chunks - BatchNoInteractivity ///< Do one large chunk, no interactivity at all - // Warning: Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) - }; + enum FillViewStrategy + { + FavorInteractivity, ///< Do small chunks of work, small intervals between chunks to allow for UI event processing + FavorSpeed, ///< Do larger chunks of work, zero intervals between chunks + BatchNoInteractivity ///< Do one large chunk, no interactivity at all + // Warning: Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) + }; private: - Grouping mGrouping; - GroupExpandPolicy mGroupExpandPolicy; - Threading mThreading; - ThreadLeader mThreadLeader; - ThreadExpandPolicy mThreadExpandPolicy; - FillViewStrategy mFillViewStrategy; + Grouping mGrouping; + GroupExpandPolicy mGroupExpandPolicy; + Threading mThreading; + ThreadLeader mThreadLeader; + ThreadExpandPolicy mThreadExpandPolicy; + FillViewStrategy mFillViewStrategy; public: - explicit Aggregation(); - explicit Aggregation( const Aggregation &opt ); - explicit Aggregation( - const QString &name, - const QString &description, - Grouping grouping, - GroupExpandPolicy groupExpandPolicy, - Threading threading, - ThreadLeader threadLeader, - ThreadExpandPolicy threadExpandPolicy, - FillViewStrategy fillViewStrategy, - bool readOnly ); - static bool compareName( Aggregation *agg1, Aggregation *agg2 ) - { - return ( agg1->name() < agg2->name() ); - } + explicit Aggregation(); + explicit Aggregation( const Aggregation &opt ); + explicit Aggregation( + const QString &name, + const QString &description, + Grouping grouping, + GroupExpandPolicy groupExpandPolicy, + Threading threading, + ThreadLeader threadLeader, + ThreadExpandPolicy threadExpandPolicy, + FillViewStrategy fillViewStrategy, + bool readOnly ); + static bool compareName( Aggregation *agg1, Aggregation *agg2 ) + { + return ( agg1->name() < agg2->name() ); + } public: - /** + /** * Returns the currently set Grouping option. */ - Grouping grouping() const + Grouping grouping() const { return mGrouping; } - /** + /** * Sets the Grouping option. */ - void setGrouping( Grouping g ) + void setGrouping( Grouping g ) { mGrouping = g; } - /** + /** * Enumerates the available grouping options as a QList of * pairs in that the first item is the localized description of the * option value and the second item is the integer option value itself. */ - static QList< QPair< QString, int > > enumerateGroupingOptions(); + static QList< QPair< QString, int > > enumerateGroupingOptions(); - /** + /** * Returns the current GroupExpandPolicy. */ - GroupExpandPolicy groupExpandPolicy() const + GroupExpandPolicy groupExpandPolicy() const { return mGroupExpandPolicy; } - /** + /** * Sets the GroupExpandPolicy for the groups. * Note that this option has no meaning if grouping is set to NoGrouping. */ - void setGroupExpandPolicy( GroupExpandPolicy groupExpandPolicy ) + void setGroupExpandPolicy( GroupExpandPolicy groupExpandPolicy ) { mGroupExpandPolicy = groupExpandPolicy; } - /** + /** * Enumerates the group sort direction options compatible with the specified Grouping. * The returned descriptors are pairs in that the first item is the localized description * of the option value and the second item is the integer option value itself. * If the returned list is empty then the value of the option is meaningless in the current context. */ - static QList< QPair< QString, int > > enumerateGroupExpandPolicyOptions( Grouping g ); + static QList< QPair< QString, int > > enumerateGroupExpandPolicyOptions( Grouping g ); - /** + /** * Returns the current threading method. */ - Threading threading() const + Threading threading() const { return mThreading; } - /** + /** * Sets the threading method option. */ - void setThreading( Threading t ) + void setThreading( Threading t ) { mThreading = t; } - /** + /** * Enumerates the available threading method options. * The returned descriptors are pairs in that the first item is the localized description * of the option value and the second item is the integer option value itself. */ - static QList< QPair< QString, int > > enumerateThreadingOptions(); + static QList< QPair< QString, int > > enumerateThreadingOptions(); - /** + /** * Returns the current thread leader determination method. */ - ThreadLeader threadLeader() const + ThreadLeader threadLeader() const { return mThreadLeader; } - /** + /** * Sets the current thread leader determination method. * Please note that when Threading is set to NoThreading this value is meaningless * and by policy should be set to TopmostMessage. */ - void setThreadLeader( ThreadLeader tl ) + void setThreadLeader( ThreadLeader tl ) { mThreadLeader = tl; } - /** + /** * Enumerates the thread leader determination methods compatible with the specified Threading * and the specified Gouping options. * The returned descriptors are pairs in that the first item is the localized description * of the option value and the second item is the integer option value itself. * If the returned list is empty then the value of the option is meaningless in the current context. */ - static QList< QPair< QString, int > > enumerateThreadLeaderOptions( Grouping g, Threading t ); + static QList< QPair< QString, int > > enumerateThreadLeaderOptions( Grouping g, Threading t ); - /** + /** * Returns the current thread expand policy. */ - ThreadExpandPolicy threadExpandPolicy() const + ThreadExpandPolicy threadExpandPolicy() const { return mThreadExpandPolicy; } - /** + /** * Sets the current thread expand policy. * Please note that when Threading is set to NoThreading this value is meaningless * and by policy should be set to NeverExpandThreads. */ - void setThreadExpandPolicy( ThreadExpandPolicy threadExpandPolicy ) + void setThreadExpandPolicy( ThreadExpandPolicy threadExpandPolicy ) { mThreadExpandPolicy = threadExpandPolicy; } - /** + /** * Enumerates the thread expand policies compatible with the specified Threading option. * The returned descriptors are pairs in that the first item is the localized description * of the option value and the second item is the integer option value itself. * If the returned list is empty then the value of the option is meaningless in the current context. */ - static QList< QPair< QString, int > > enumerateThreadExpandPolicyOptions( Threading t ); + static QList< QPair< QString, int > > enumerateThreadExpandPolicyOptions( Threading t ); - /** + /** * Returns the current fill view strategy. */ - FillViewStrategy fillViewStrategy() const + FillViewStrategy fillViewStrategy() const { return mFillViewStrategy; } - /** + /** * Sets the current fill view strategy. */ - void setFillViewStrategy( FillViewStrategy fillViewStrategy ) + void setFillViewStrategy( FillViewStrategy fillViewStrategy ) { mFillViewStrategy = fillViewStrategy; } - /** + /** * Enumerates the fill view strategies. * The returned descriptors are pairs in that the first item is the localized description * of the option value and the second item is the integer option value itself. */ - static QList< QPair< QString, int > > enumerateFillViewStrategyOptions(); + static QList< QPair< QString, int > > enumerateFillViewStrategyOptions(); - /** + /** * Pure virtual reimplemented from OptionSet. */ - virtual void save( QDataStream &stream ) const; + virtual void save( QDataStream &stream ) const; - /** + /** * Pure virtual reimplemented from OptionSet. */ - virtual bool load( QDataStream &stream ); + virtual bool load( QDataStream &stream ); }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/delegate.cpp kdepim-4.13.0/messagelist/core/delegate.cpp --- kdepim-4.12.97/messagelist/core/delegate.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/delegate.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -26,7 +26,7 @@ using namespace MessageList::Core; Delegate::Delegate( View *pParent ) - : ThemeDelegate( pParent ) + : ThemeDelegate( pParent ) { } @@ -36,6 +36,6 @@ Item * Delegate::itemFromIndex( const QModelIndex &index ) const { - return static_cast< Item * >( index.internalPointer() ); + return static_cast< Item * >( index.internalPointer() ); } diff -Nru kdepim-4.12.97/messagelist/core/delegate.h kdepim-4.13.0/messagelist/core/delegate.h --- kdepim-4.12.97/messagelist/core/delegate.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/delegate.h 2014-04-10 07:40:20.000000000 +0000 @@ -34,14 +34,14 @@ class Delegate : public ThemeDelegate { public: - explicit Delegate( View *pParent ); - ~Delegate(); + explicit Delegate( View *pParent ); + ~Delegate(); protected: - /** + /** * Returns the Item for the specified model index. Reimplemented from ThemeDelegate. */ - virtual Item * itemFromIndex( const QModelIndex &index ) const; + virtual Item * itemFromIndex( const QModelIndex &index ) const; }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/filter.h kdepim-4.13.0/messagelist/core/filter.h --- kdepim-4.12.97/messagelist/core/filter.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/filter.h 2014-04-10 07:40:20.000000000 +0000 @@ -43,79 +43,79 @@ */ class Filter : public QObject { - Q_OBJECT + Q_OBJECT public: - Filter(); + Filter(); public: - /** + /** * Returns true if the specified parameters match this filter and false otherwise. * The msg pointer must not be null. */ - bool match( const MessageItem * item ) const; + bool match( const MessageItem * item ) const; - /** + /** * Returns the currently set status mask */ - QList status() const - { return mStatus; } + QList status() const + { return mStatus; } - /** + /** * Sets the status mask for this filter. */ - void setStatus( const QList &lstStatus ) - { mStatus = lstStatus; } + void setStatus( const QList &lstStatus ) + { mStatus = lstStatus; } - /** + /** * Sets the current folder of this filter. */ - void setCurrentFolder( const Akonadi::Collection &collection ); + void setCurrentFolder( const Akonadi::Collection &collection ); - /** + /** * Returns the currently set search string. */ - const QString & searchString() const - { return mSearchString; } + const QString & searchString() const + { return mSearchString; } - /** + /** * Sets the search string for this filter. */ - void setSearchString(const QString &search, QuickSearchLine::SearchOptions options); + void setSearchString(const QString &search, QuickSearchLine::SearchOptions options); - /** + /** * Returns the currently set MessageItem::Tag id */ - const QString & tagId() const - { return mTagId; } + const QString & tagId() const + { return mTagId; } - /** + /** * Sets the id of a MessageItem::Tag that the matching messages must contain. */ - void setTagId( const QString &tagId ) - { mTagId = tagId; } + void setTagId( const QString &tagId ) + { mTagId = tagId; } - /** + /** * Clears this filter (sets status to 0, search string and tag id to empty strings) */ - void clear(); + void clear(); - /** + /** * Returns true if this filter is empty (0 status mask, empty search string and empty tag) * and it's useless to call match() that will always return true. */ - bool isEmpty() const; + bool isEmpty() const; Q_SIGNALS: - void finished(); + void finished(); private: - QList mStatus; ///< Messages must match theses status, if non 0 - QString mSearchString; ///< Messages must match this search string, if not empty - QString mTagId; ///< Messages must have this tag, if not empty. Contains a tag url. - Akonadi::Collection mCurrentFolder; - QSet mMatchingItemIds; - QuickSearchLine::SearchOptions mOptions; + QList mStatus; ///< Messages must match theses status, if non 0 + QString mSearchString; ///< Messages must match this search string, if not empty + QString mTagId; ///< Messages must have this tag, if not empty. Contains a tag url. + Akonadi::Collection mCurrentFolder; + QSet mMatchingItemIds; + QuickSearchLine::SearchOptions mOptions; }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/groupheaderitem.cpp kdepim-4.13.0/messagelist/core/groupheaderitem.cpp --- kdepim-4.12.97/messagelist/core/groupheaderitem.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/groupheaderitem.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -23,7 +23,7 @@ using namespace MessageList::Core; GroupHeaderItem::GroupHeaderItem( const QString &label ) - : Item( GroupHeader ), mLabel( label ) + : Item( GroupHeader ), mLabel( label ) { } diff -Nru kdepim-4.12.97/messagelist/core/groupheaderitem.h kdepim-4.13.0/messagelist/core/groupheaderitem.h --- kdepim-4.12.97/messagelist/core/groupheaderitem.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/groupheaderitem.h 2014-04-10 07:40:20.000000000 +0000 @@ -34,14 +34,14 @@ class GroupHeaderItem : public Item { public: - explicit GroupHeaderItem( const QString &label ); - virtual ~GroupHeaderItem(); + explicit GroupHeaderItem( const QString &label ); + virtual ~GroupHeaderItem(); + + const QString & label() const; + void setLabel( const QString &label ); - const QString & label() const; - void setLabel( const QString &label ); - private: - QString mLabel; + QString mLabel; }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/item.cpp kdepim-4.13.0/messagelist/core/item.cpp --- kdepim-4.12.97/messagelist/core/item.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/item.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -31,143 +31,143 @@ using namespace MessageList::Core; Item::Item( Type type ) - : d_ptr( new ItemPrivate( this ) ) + : d_ptr( new ItemPrivate( this ) ) { - d_ptr->mType = type; + d_ptr->mType = type; } Item::Item ( Item::Type type, ItemPrivate* dd ) - : d_ptr( dd ) + : d_ptr( dd ) { - d_ptr->mType = type; + d_ptr->mType = type; } Item::~Item() { - killAllChildItems(); + killAllChildItems(); - if ( d_ptr->mParent ) - d_ptr->mParent->d_ptr->childItemDead( this ); + if ( d_ptr->mParent ) + d_ptr->mParent->d_ptr->childItemDead( this ); - delete d_ptr; + delete d_ptr; } void Item::childItemStats( ChildItemStats &stats ) const { - Q_ASSERT( d_ptr->mChildItems ); + Q_ASSERT( d_ptr->mChildItems ); - stats.mTotalChildCount += d_ptr->mChildItems->count(); - QList< Item * >::ConstIterator end( d_ptr->mChildItems->constEnd() ); - for( QList< Item * >::ConstIterator it = d_ptr->mChildItems->constBegin(); it != end; ++it ) - { - if ( !( *it )->status().isRead() ) - stats.mUnreadChildCount++; - if ( ( *it )->d_ptr->mChildItems ) - ( *it )->childItemStats( stats ); - } + stats.mTotalChildCount += d_ptr->mChildItems->count(); + QList< Item * >::ConstIterator end( d_ptr->mChildItems->constEnd() ); + for( QList< Item * >::ConstIterator it = d_ptr->mChildItems->constBegin(); it != end; ++it ) + { + if ( !( *it )->status().isRead() ) + stats.mUnreadChildCount++; + if ( ( *it )->d_ptr->mChildItems ) + ( *it )->childItemStats( stats ); + } } QList< Item * > *Item::childItems() const { - return d_ptr->mChildItems; + return d_ptr->mChildItems; } Item *Item::childItem( int idx ) const { - if ( idx < 0 ) - return 0; - if ( !d_ptr->mChildItems ) - return 0; - if ( d_ptr->mChildItems->count() <= idx ) - return 0; - return d_ptr->mChildItems->at( idx ); + if ( idx < 0 ) + return 0; + if ( !d_ptr->mChildItems ) + return 0; + if ( d_ptr->mChildItems->count() <= idx ) + return 0; + return d_ptr->mChildItems->at( idx ); } Item * Item::firstChildItem() const { - return d_ptr->mChildItems ? ( d_ptr->mChildItems->count() > 0 ? d_ptr->mChildItems->at( 0 ) : 0 ) : 0; + return d_ptr->mChildItems ? ( d_ptr->mChildItems->count() > 0 ? d_ptr->mChildItems->at( 0 ) : 0 ) : 0; } Item * Item::itemBelowChild( Item * child ) { - Q_ASSERT( d_ptr->mChildItems ); + Q_ASSERT( d_ptr->mChildItems ); - int idx = indexOfChildItem(child); - Q_ASSERT( idx >= 0 ); + int idx = indexOfChildItem(child); + Q_ASSERT( idx >= 0 ); - idx++; + idx++; - if ( idx < d_ptr->mChildItems->count() ) - return d_ptr->mChildItems->at( idx ); + if ( idx < d_ptr->mChildItems->count() ) + return d_ptr->mChildItems->at( idx ); - if ( !d_ptr->mParent ) - return 0; + if ( !d_ptr->mParent ) + return 0; - return d_ptr->mParent->itemBelowChild( this ); + return d_ptr->mParent->itemBelowChild( this ); } Item * Item::itemBelow() { - if ( d_ptr->mChildItems ) - { - if ( !d_ptr->mChildItems->isEmpty() ) - return d_ptr->mChildItems->at( 0 ); - } + if ( d_ptr->mChildItems ) + { + if ( !d_ptr->mChildItems->isEmpty() ) + return d_ptr->mChildItems->at( 0 ); + } - if ( !d_ptr->mParent ) - return 0; + if ( !d_ptr->mParent ) + return 0; - return d_ptr->mParent->itemBelowChild( this ); + return d_ptr->mParent->itemBelowChild( this ); } Item * Item::deepestItem() { - if ( d_ptr->mChildItems ) - { - if ( !d_ptr->mChildItems->isEmpty() ) - return d_ptr->mChildItems->at( d_ptr->mChildItems->count() - 1 )->deepestItem(); - } + if ( d_ptr->mChildItems ) + { + if ( !d_ptr->mChildItems->isEmpty() ) + return d_ptr->mChildItems->at( d_ptr->mChildItems->count() - 1 )->deepestItem(); + } - return this; + return this; } Item * Item::itemAboveChild( Item * child ) { - if ( d_ptr->mChildItems ) - { - int idx = indexOfChildItem(child); - Q_ASSERT( idx >= 0 ); - idx--; + if ( d_ptr->mChildItems ) + { + int idx = indexOfChildItem(child); + Q_ASSERT( idx >= 0 ); + idx--; - if ( idx >= 0 ) - return d_ptr->mChildItems->at( idx ); - } + if ( idx >= 0 ) + return d_ptr->mChildItems->at( idx ); + } - return this; + return this; } Item * Item::itemAbove() { - if ( !d_ptr->mParent ) - return 0; + if ( !d_ptr->mParent ) + return 0; - Item *siblingAbove = d_ptr->mParent->itemAboveChild( this ); - if ( siblingAbove && siblingAbove != this && siblingAbove != d_ptr->mParent && - siblingAbove->childItemCount() > 0 ) { - return siblingAbove->deepestItem(); - } + Item *siblingAbove = d_ptr->mParent->itemAboveChild( this ); + if ( siblingAbove && siblingAbove != this && siblingAbove != d_ptr->mParent && + siblingAbove->childItemCount() > 0 ) { + return siblingAbove->deepestItem(); + } - return d_ptr->mParent->itemAboveChild( this ); + return d_ptr->mParent->itemAboveChild( this ); } int Item::childItemCount() const { - return d_ptr->mChildItems ? d_ptr->mChildItems->count() : 0; + return d_ptr->mChildItems ? d_ptr->mChildItems->count() : 0; } bool Item::hasChildren() const { - return childItemCount() > 0; + return childItemCount() > 0; } int Item::indexOfChildItem( Item *child ) const @@ -186,296 +186,296 @@ void Item::setIndexGuess( int index ) { - d_ptr->mThisItemIndexGuess = index; + d_ptr->mThisItemIndexGuess = index; } Item * Item::topmostNonRoot() { - Q_ASSERT( d_ptr->mType != InvisibleRoot ); + Q_ASSERT( d_ptr->mType != InvisibleRoot ); - if ( !d_ptr->mParent ) - return this; + if ( !d_ptr->mParent ) + return this; - if ( d_ptr->mParent->type() == InvisibleRoot ) - return this; + if ( d_ptr->mParent->type() == InvisibleRoot ) + return this; - return d_ptr->mParent->topmostNonRoot(); + return d_ptr->mParent->topmostNonRoot(); } static inline void append_string( QString &buffer, const QString &append ) { - if ( !buffer.isEmpty() ) - buffer += QLatin1String( ", " ); - buffer += append; + if ( !buffer.isEmpty() ) + buffer += QLatin1String( ", " ); + buffer += append; } QString Item::statusDescription() const { - QString ret; - if( status().isRead() ) - append_string( ret, i18nc( "Status of an item", "Read" ) ); - else - append_string( ret, i18nc( "Status of an item", "Unread" ) ); + QString ret; + if( status().isRead() ) + append_string( ret, i18nc( "Status of an item", "Read" ) ); + else + append_string( ret, i18nc( "Status of an item", "Unread" ) ); - if( status().hasAttachment() ) - append_string( ret, i18nc( "Status of an item", "Has Attachment" ) ); + if( status().hasAttachment() ) + append_string( ret, i18nc( "Status of an item", "Has Attachment" ) ); - if( status().isToAct() ) - append_string( ret, i18nc( "Status of an item", "Action Item" ) ); + if( status().isToAct() ) + append_string( ret, i18nc( "Status of an item", "Action Item" ) ); - if( status().isReplied() ) - append_string( ret, i18nc( "Status of an item", "Replied" ) ); + if( status().isReplied() ) + append_string( ret, i18nc( "Status of an item", "Replied" ) ); - if( status().isForwarded() ) - append_string( ret, i18nc( "Status of an item", "Forwarded" ) ); + if( status().isForwarded() ) + append_string( ret, i18nc( "Status of an item", "Forwarded" ) ); - if( status().isSent() ) - append_string( ret, i18nc( "Status of an item", "Sent" ) ); + if( status().isSent() ) + append_string( ret, i18nc( "Status of an item", "Sent" ) ); - if( status().isImportant() ) - append_string( ret, i18nc( "Status of an item", "Important" ) ); + if( status().isImportant() ) + append_string( ret, i18nc( "Status of an item", "Important" ) ); - if( status().isSpam() ) - append_string( ret, i18nc( "Status of an item", "Spam" ) ); + if( status().isSpam() ) + append_string( ret, i18nc( "Status of an item", "Spam" ) ); - if( status().isHam() ) - append_string( ret, i18nc( "Status of an item", "Ham" ) ); + if( status().isHam() ) + append_string( ret, i18nc( "Status of an item", "Ham" ) ); - if( status().isWatched() ) - append_string( ret, i18nc( "Status of an item", "Watched" ) ); + if( status().isWatched() ) + append_string( ret, i18nc( "Status of an item", "Watched" ) ); - if( status().isIgnored() ) - append_string( ret, i18nc( "Status of an item", "Ignored" ) ); + if( status().isIgnored() ) + append_string( ret, i18nc( "Status of an item", "Ignored" ) ); - return ret; + return ret; } QString Item::formattedSize() const { - return KIO::convertSize( ( KIO::filesize_t ) size() ); + return KIO::convertSize( ( KIO::filesize_t ) size() ); } QString Item::formattedDate() const { - if ( static_cast< uint >( date() ) == static_cast< uint >( -1 ) ) - return Manager::instance()->cachedLocalizedUnknownText(); - else - return Manager::instance()->dateFormatter()->dateString( date() ); + if ( static_cast< uint >( date() ) == static_cast< uint >( -1 ) ) + return Manager::instance()->cachedLocalizedUnknownText(); + else + return Manager::instance()->dateFormatter()->dateString( date() ); } QString Item::formattedMaxDate() const { - if ( static_cast< uint >( maxDate() ) == static_cast< uint >( -1 ) ) - return Manager::instance()->cachedLocalizedUnknownText(); - else - return Manager::instance()->dateFormatter()->dateString( maxDate() ); + if ( static_cast< uint >( maxDate() ) == static_cast< uint >( -1 ) ) + return Manager::instance()->cachedLocalizedUnknownText(); + else + return Manager::instance()->dateFormatter()->dateString( maxDate() ); } bool Item::recomputeMaxDate() { - time_t newMaxDate = d_ptr->mDate; + time_t newMaxDate = d_ptr->mDate; - if ( d_ptr->mChildItems ) - { - QList< Item * >::ConstIterator end = d_ptr->mChildItems->constEnd(); - for ( QList< Item * >::ConstIterator it = d_ptr->mChildItems->constBegin(); it != end; ++it ) { - if ( ( *it )->d_ptr->mMaxDate > newMaxDate ) - newMaxDate = ( *it )->d_ptr->mMaxDate; - } - } - - if ( newMaxDate != d_ptr->mMaxDate ) - { - setMaxDate( newMaxDate ); - return true; - } - return false; + if ( d_ptr->mChildItems ) + { + QList< Item * >::ConstIterator end = d_ptr->mChildItems->constEnd(); + for ( QList< Item * >::ConstIterator it = d_ptr->mChildItems->constBegin(); it != end; ++it ) { + if ( ( *it )->d_ptr->mMaxDate > newMaxDate ) + newMaxDate = ( *it )->d_ptr->mMaxDate; + } + } + + if ( newMaxDate != d_ptr->mMaxDate ) + { + setMaxDate( newMaxDate ); + return true; + } + return false; } Item::Type Item::type() const { - return d_ptr->mType; + return d_ptr->mType; } Item::InitialExpandStatus Item::initialExpandStatus() const { - return d_ptr->mInitialExpandStatus; + return d_ptr->mInitialExpandStatus; } void Item::setInitialExpandStatus( InitialExpandStatus initialExpandStatus ) { - d_ptr->mInitialExpandStatus = initialExpandStatus; + d_ptr->mInitialExpandStatus = initialExpandStatus; } bool Item::isViewable() const { - return d_ptr->mIsViewable; + return d_ptr->mIsViewable; } bool Item::hasAncestor( const Item * it ) const { - return d_ptr->mParent ? ( d_ptr->mParent == it ? true : d_ptr->mParent->hasAncestor( it ) ) : false; + return d_ptr->mParent ? ( d_ptr->mParent == it ? true : d_ptr->mParent->hasAncestor( it ) ) : false; } void Item::setViewable( Model *model,bool bViewable ) { - if ( d_ptr->mIsViewable == bViewable ) - return; - - if ( !d_ptr->mChildItems ) { - d_ptr->mIsViewable = bViewable; - return; - } - - if ( d_ptr->mChildItems->isEmpty() ) { - d_ptr->mIsViewable = bViewable; - return; - } + if ( d_ptr->mIsViewable == bViewable ) + return; - if ( bViewable ) - { - if ( model ) - { - // fake having no children, for a second - QList< Item * > * tmp = d_ptr->mChildItems; - d_ptr->mChildItems = 0; - //qDebug("BEGIN INSERT ROWS FOR PARENT %x: from %d to %d, (will) have %d children",this,0,tmp->count()-1,tmp->count()); - model->beginInsertRows( model->index( this, 0 ), 0, tmp->count() - 1 ); - d_ptr->mChildItems = tmp; - d_ptr->mIsViewable = true; - model->endInsertRows(); - } else { - d_ptr->mIsViewable = true; + if ( !d_ptr->mChildItems ) { + d_ptr->mIsViewable = bViewable; + return; } - QList< Item * >::ConstIterator end( d_ptr->mChildItems->constEnd() ); - for ( QList< Item * >::ConstIterator it = d_ptr->mChildItems->constBegin(); it != end ;++it ) - ( *it )->setViewable( model, bViewable ); - } else { - QList< Item * >::ConstIterator end( d_ptr->mChildItems->constEnd() ); - for ( QList< Item * >::ConstIterator it = d_ptr->mChildItems->constBegin(); it != end ;++it ) - ( *it )->setViewable( model, bViewable ); - - // It seems that we can avoid removing child items here since the parent has been removed: this is a hack tough - // and should check if Qt4 still supports it in the next (hopefully largely fixed) release + if ( d_ptr->mChildItems->isEmpty() ) { + d_ptr->mIsViewable = bViewable; + return; + } - if ( model ) + if ( bViewable ) { - // fake having no children, for a second - model->beginRemoveRows( model->index( this, 0 ), 0, d_ptr->mChildItems->count() - 1 ); - QList< Item * > * tmp = d_ptr->mChildItems; - d_ptr->mChildItems = 0; - d_ptr->mIsViewable = false; - model->endRemoveRows(); - d_ptr->mChildItems = tmp; + if ( model ) + { + // fake having no children, for a second + QList< Item * > * tmp = d_ptr->mChildItems; + d_ptr->mChildItems = 0; + //qDebug("BEGIN INSERT ROWS FOR PARENT %x: from %d to %d, (will) have %d children",this,0,tmp->count()-1,tmp->count()); + model->beginInsertRows( model->index( this, 0 ), 0, tmp->count() - 1 ); + d_ptr->mChildItems = tmp; + d_ptr->mIsViewable = true; + model->endInsertRows(); + } else { + d_ptr->mIsViewable = true; + } + + QList< Item * >::ConstIterator end( d_ptr->mChildItems->constEnd() ); + for ( QList< Item * >::ConstIterator it = d_ptr->mChildItems->constBegin(); it != end ;++it ) + ( *it )->setViewable( model, bViewable ); } else { - d_ptr->mIsViewable = false; + QList< Item * >::ConstIterator end( d_ptr->mChildItems->constEnd() ); + for ( QList< Item * >::ConstIterator it = d_ptr->mChildItems->constBegin(); it != end ;++it ) + ( *it )->setViewable( model, bViewable ); + + // It seems that we can avoid removing child items here since the parent has been removed: this is a hack tough + // and should check if Qt4 still supports it in the next (hopefully largely fixed) release + + if ( model ) + { + // fake having no children, for a second + model->beginRemoveRows( model->index( this, 0 ), 0, d_ptr->mChildItems->count() - 1 ); + QList< Item * > * tmp = d_ptr->mChildItems; + d_ptr->mChildItems = 0; + d_ptr->mIsViewable = false; + model->endRemoveRows(); + d_ptr->mChildItems = tmp; + } else { + d_ptr->mIsViewable = false; + } } - } } void Item::killAllChildItems() { - if ( !d_ptr->mChildItems ) - return; + if ( !d_ptr->mChildItems ) + return; - while( !d_ptr->mChildItems->isEmpty() ) - delete d_ptr->mChildItems->first(); // this will call childDead() which will remove the child from the list + while( !d_ptr->mChildItems->isEmpty() ) + delete d_ptr->mChildItems->first(); // this will call childDead() which will remove the child from the list - delete d_ptr->mChildItems; - d_ptr->mChildItems = 0; + delete d_ptr->mChildItems; + d_ptr->mChildItems = 0; } Item * Item::parent() const { - return d_ptr->mParent; + return d_ptr->mParent; } void Item::setParent( Item *pParent ) { - d_ptr->mParent = pParent; + d_ptr->mParent = pParent; } const Akonadi::MessageStatus &Item::status() const { - return d_ptr->mStatus; + return d_ptr->mStatus; } void Item::setStatus( const Akonadi::MessageStatus &status ) { - d_ptr->mStatus = status; + d_ptr->mStatus = status; } size_t Item::size() const { - return d_ptr->mSize; + return d_ptr->mSize; } void Item::setSize( size_t size ) { - d_ptr->mSize = size; + d_ptr->mSize = size; } time_t Item::date() const { - return d_ptr->mDate; + return d_ptr->mDate; } void Item::setDate( time_t date ) { - d_ptr->mDate = date; + d_ptr->mDate = date; } time_t Item::maxDate() const { - return d_ptr->mMaxDate; + return d_ptr->mMaxDate; } void Item::setMaxDate( time_t date ) { - d_ptr->mMaxDate = date; + d_ptr->mMaxDate = date; } const QString &Item::sender() const { - return d_ptr->mSender; + return d_ptr->mSender; } void Item::setSender( const QString &sender ) { - d_ptr->mSender = sender; + d_ptr->mSender = sender; } const QString &Item::receiver() const { - return d_ptr->mReceiver; + return d_ptr->mReceiver; } void Item::setReceiver( const QString &receiver ) { - d_ptr->mReceiver = receiver; + d_ptr->mReceiver = receiver; } const QString &Item::senderOrReceiver() const { - return d_ptr->mUseReceiver ? d_ptr->mReceiver : d_ptr->mSender; + return d_ptr->mUseReceiver ? d_ptr->mReceiver : d_ptr->mSender; } bool Item::useReceiver() const { - return d_ptr->mUseReceiver; + return d_ptr->mUseReceiver; } const QString &Item::subject() const { - return d_ptr->mSubject; + return d_ptr->mSubject; } void Item::setSubject( const QString &subject ) { - d_ptr->mSubject = subject; + d_ptr->mSubject = subject; } void MessageList::Core::Item::initialSetup( time_t date, size_t size, @@ -483,125 +483,125 @@ const QString &receiver, bool useReceiver ) { - d_ptr->mDate = date; - d_ptr->mMaxDate = date; - d_ptr->mSize = size; - d_ptr->mSender = sender; - d_ptr->mReceiver = receiver; - d_ptr->mUseReceiver = useReceiver; + d_ptr->mDate = date; + d_ptr->mMaxDate = date; + d_ptr->mSize = size; + d_ptr->mSender = sender; + d_ptr->mReceiver = receiver; + d_ptr->mUseReceiver = useReceiver; } void MessageList::Core::Item::setItemId(qint64 id) { - d_ptr->mItemId = id; + d_ptr->mItemId = id; } qint64 MessageList::Core::Item::itemId() const { - return d_ptr->mItemId; + return d_ptr->mItemId; } void MessageList::Core::Item::setSubjectAndStatus(const QString &subject, const Akonadi::MessageStatus &status) { - d_ptr->mSubject = subject; - d_ptr->mStatus = status; + d_ptr->mSubject = subject; + d_ptr->mStatus = status; } // FIXME: Try to "cache item insertions" and call beginInsertRows() and endInsertRows() in a chunked fashion... void Item::rawAppendChildItem( Item * child ) { - if ( !d_ptr->mChildItems ) - d_ptr->mChildItems = new QList< Item * >(); - d_ptr->mChildItems->append( child ); + if ( !d_ptr->mChildItems ) + d_ptr->mChildItems = new QList< Item * >(); + d_ptr->mChildItems->append( child ); } int Item::appendChildItem( Model *model, Item *child ) { - if ( !d_ptr->mChildItems ) - d_ptr->mChildItems = new QList< Item * >(); - const int idx = d_ptr->mChildItems->count(); - if ( d_ptr->mIsViewable ) - { - if ( model ) - model->beginInsertRows( model->index( this, 0 ), idx, idx ); // THIS IS EXTREMELY UGLY, BUT IT'S THE ONLY POSSIBLE WAY WITH QT4 AT THE TIME OF WRITING - d_ptr->mChildItems->append( child ); - child->setIndexGuess( idx ); - if ( model ) - model->endInsertRows(); // THIS IS EXTREMELY UGLY, BUT IT'S THE ONLY POSSIBLE WAY WITH QT4 AT THE TIME OF WRITING - child->setViewable( model, true ); - } else { - d_ptr->mChildItems->append( child ); - child->setIndexGuess( idx ); - } - return idx; + if ( !d_ptr->mChildItems ) + d_ptr->mChildItems = new QList< Item * >(); + const int idx = d_ptr->mChildItems->count(); + if ( d_ptr->mIsViewable ) + { + if ( model ) + model->beginInsertRows( model->index( this, 0 ), idx, idx ); // THIS IS EXTREMELY UGLY, BUT IT'S THE ONLY POSSIBLE WAY WITH QT4 AT THE TIME OF WRITING + d_ptr->mChildItems->append( child ); + child->setIndexGuess( idx ); + if ( model ) + model->endInsertRows(); // THIS IS EXTREMELY UGLY, BUT IT'S THE ONLY POSSIBLE WAY WITH QT4 AT THE TIME OF WRITING + child->setViewable( model, true ); + } else { + d_ptr->mChildItems->append( child ); + child->setIndexGuess( idx ); + } + return idx; } void Item::dump( const QString &prefix ) { - QString out = QString::fromLatin1( "%1 %x VIEWABLE:%2" ).arg(prefix).arg(d_ptr->mIsViewable ? QLatin1String( "yes" ) : QLatin1String( "no" )); - qDebug( out.toUtf8().data(),this ); + QString out = QString::fromLatin1( "%1 %x VIEWABLE:%2" ).arg(prefix).arg(d_ptr->mIsViewable ? QLatin1String( "yes" ) : QLatin1String( "no" )); + qDebug( out.toUtf8().data(),this ); - QString nPrefix( prefix ); - nPrefix += QLatin1String(" "); + QString nPrefix( prefix ); + nPrefix += QLatin1String(" "); - if (!d_ptr->mChildItems ) - return; + if (!d_ptr->mChildItems ) + return; - QList< Item * >::ConstIterator end( d_ptr->mChildItems->constEnd() ); - for ( QList< Item * >::ConstIterator it = d_ptr->mChildItems->constBegin(); it != end ;++it ) - (*it)->dump(nPrefix); + QList< Item * >::ConstIterator end( d_ptr->mChildItems->constEnd() ); + for ( QList< Item * >::ConstIterator it = d_ptr->mChildItems->constBegin(); it != end ;++it ) + (*it)->dump(nPrefix); } void Item::takeChildItem( Model *model, Item *child ) { - if ( !d_ptr->mChildItems ) - return; // Ugh... not our child ? + if ( !d_ptr->mChildItems ) + return; // Ugh... not our child ? - if ( !d_ptr->mIsViewable ) - { - //qDebug("TAKING NON VIEWABLE CHILD ITEM %x",child); - // We can highly optimize this case - d_ptr->mChildItems->removeOne( child ); -#if 0 - // This *could* be done, but we optimize and avoid it. - if ( d->mChildItems->isEmpty() ) + if ( !d_ptr->mIsViewable ) { - delete d->mChildItems; - d->mChildItems = 0; - } + //qDebug("TAKING NON VIEWABLE CHILD ITEM %x",child); + // We can highly optimize this case + d_ptr->mChildItems->removeOne( child ); +#if 0 + // This *could* be done, but we optimize and avoid it. + if ( d->mChildItems->isEmpty() ) + { + delete d->mChildItems; + d->mChildItems = 0; + } #endif - child->setParent( 0 ); - return; - } + child->setParent( 0 ); + return; + } - const int idx = indexOfChildItem(child); - if (idx < 0) - return; // Aaargh... not our child ? - - child->setViewable( model, false ); - if ( model ) - model->beginRemoveRows( model->index( this, 0 ), idx, idx ); - child->setParent( 0 ); - d_ptr->mChildItems->removeAt( idx ); - if ( model ) - model->endRemoveRows(); + const int idx = indexOfChildItem(child); + if (idx < 0) + return; // Aaargh... not our child ? + + child->setViewable( model, false ); + if ( model ) + model->beginRemoveRows( model->index( this, 0 ), idx, idx ); + child->setParent( 0 ); + d_ptr->mChildItems->removeAt( idx ); + if ( model ) + model->endRemoveRows(); #if 0 - // This *could* be done, but we optimize and avoid it. - if ( d->mChildItems->isEmpty() ) - { - delete d->mChildItems; - d->mChildItems = 0; - } + // This *could* be done, but we optimize and avoid it. + if ( d->mChildItems->isEmpty() ) + { + delete d->mChildItems; + d->mChildItems = 0; + } #endif } void ItemPrivate::childItemDead( Item *child ) { - // mChildItems MUST be non zero here, if it's not then it's a bug in THIS FILE - mChildItems->removeOne( child ); // since we always have ONE (if we not, it's a bug) + // mChildItems MUST be non zero here, if it's not then it's a bug in THIS FILE + mChildItems->removeOne( child ); // since we always have ONE (if we not, it's a bug) } diff -Nru kdepim-4.12.97/messagelist/core/item.h kdepim-4.13.0/messagelist/core/item.h --- kdepim-4.12.97/messagelist/core/item.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/item.h 2014-04-10 07:40:20.000000000 +0000 @@ -51,168 +51,168 @@ */ class MESSAGELIST_EXPORT Item { - friend class Model; - friend class ModelPrivate; + friend class Model; + friend class ModelPrivate; public: - /** + /** * The type of the Item. */ - enum Type - { - GroupHeader, ///< This item is a GroupHeaderItem - Message, ///< This item is a MessageItem - InvisibleRoot ///< This item is just Item and it's the only InvisibleRoot per Model. - }; + enum Type + { + GroupHeader, ///< This item is a GroupHeaderItem + Message, ///< This item is a MessageItem + InvisibleRoot ///< This item is just Item and it's the only InvisibleRoot per Model. + }; - /** + /** * Specifies the initial expand status for the item that should be applied * when it's attached to the viewable tree. Needed as a workaround for * QTreeView limitations in handling item expansion. */ - enum InitialExpandStatus - { - ExpandNeeded, ///< Must expand when this item becomes viewable - NoExpandNeeded, ///< No expand needed at all - ExpandExecuted ///< Item already expanded - }; + enum InitialExpandStatus + { + ExpandNeeded, ///< Must expand when this item becomes viewable + NoExpandNeeded, ///< No expand needed at all + ExpandExecuted ///< Item already expanded + }; protected: - /** + /** * Creates an Item. Only derived classes and MessageList::Model should access this. */ - Item( Type type ); - Item( Type type, ItemPrivate *dd ); + Item( Type type ); + Item( Type type, ItemPrivate *dd ); public: - /** + /** * Destroys the Item. Should be protected just like the constructor but the QList<> * helpers need to access it, so it's public actually. */ - virtual ~Item(); + virtual ~Item(); - /** + /** * Returns the type of this item. The Type can be set only in the constructor. */ - Type type() const; + Type type() const; - /** + /** * The initial expand status we have to honor when attacching to the viewable root. */ - InitialExpandStatus initialExpandStatus() const; + InitialExpandStatus initialExpandStatus() const; - /** + /** * Set the initial expand status we have to honor when attacching to the viewable root. */ - void setInitialExpandStatus( InitialExpandStatus initialExpandStatus ); + void setInitialExpandStatus( InitialExpandStatus initialExpandStatus ); - /** + /** * Is this item attached to the viewable root ? */ - bool isViewable() const; + bool isViewable() const; - /** + /** * Return true if Item pointed by it is an ancestor of this item (that is, * if it is its parent, parent of its parent, parent of its parent of its parent etc... */ - bool hasAncestor( const Item * it ) const; + bool hasAncestor( const Item * it ) const; - /** + /** * Makes this item viewable, that is, notifies its existence to any listener * attacched to the "rowsInserted()" signal, most notably QTreeView. * * This will also make all the children viewable. */ - void setViewable( Model *model, bool bViewable ); + void setViewable( Model *model, bool bViewable ); - /** + /** * Return the list of child items. May be null. */ - QList< Item * > * childItems() const; + QList< Item * > * childItems() const; - /** + /** * Returns the child item at position idx or 0 if idx is out of the allowable range. */ - Item * childItem( int idx ) const; + Item * childItem( int idx ) const; - /** + /** * Returns the first child item, if any. */ - Item * firstChildItem() const; + Item * firstChildItem() const; - /** + /** * Returns the item that is visually below the specified child if this item. * Note that the returned item may belong to a completely different subtree. */ - Item * itemBelowChild( Item * child ); + Item * itemBelowChild( Item * child ); - /** + /** * Returns the item that is visually above the specified child if this item. * Note that the returned item may belong to a completely different subtree. */ - Item * itemAboveChild( Item * child ); + Item * itemAboveChild( Item * child ); - /** + /** * Returns the deepest item in the subtree originating at this item. */ - Item * deepestItem(); + Item * deepestItem(); - /** + /** * Returns the item that is visually below this item in the tree. * Note that the returned item may belong to a completely different subtree. */ - Item * itemBelow(); + Item * itemBelow(); - /** + /** * Returns the item that is visually above this item in the tree. * Note that the returned item may belong to a completely different subtree. */ - Item * itemAbove(); + Item * itemAbove(); - /** + /** * Debug helper. Dumps the structure of this subtree. */ - void dump( const QString &prefix ); + void dump( const QString &prefix ); - /** + /** * Returns the number of children of this Item. */ - int childItemCount() const; + int childItemCount() const; - /** + /** * Convenience function that returns true if this item has children. */ - bool hasChildren() const; + bool hasChildren() const; - /** + /** * A structure used with MessageList::Item::childItemStats(). * Contains counts of total and unread messages in a subtree. */ - class ChildItemStats - { - public: - unsigned int mTotalChildCount; // total - unsigned int mUnreadChildCount; // unread only - public: - ChildItemStats() - : mTotalChildCount( 0 ), mUnreadChildCount( 0 ) - {} - }; + class ChildItemStats + { + public: + unsigned int mTotalChildCount; // total + unsigned int mUnreadChildCount; // unread only + public: + ChildItemStats() + : mTotalChildCount( 0 ), mUnreadChildCount( 0 ) + {} + }; - /** + /** * Gathers statistics about child items. * For performance purposes assumes that this item has children. * You MUST check it before calling it. */ - void childItemStats( ChildItemStats &stats ) const; + void childItemStats( ChildItemStats &stats ) const; - /** + /** * Returns the actual index of the child Item item or -1 if * item is not a child of this Item. */ - int indexOfChildItem( Item *item ) const; + int indexOfChildItem( Item *item ) const; - /** + /** * Sets the cached guess for the index of this item in the parent's child list. * * This is used to speed up the index lookup with the following algorithm: @@ -220,184 +220,184 @@ * If the position matches we have finished, if it doesn't then perform * a linear search via indexOfChildItem() (which costs ~O(n)). */ - void setIndexGuess( int index ); + void setIndexGuess( int index ); - /** + /** * Returns the parent Item in the tree, or 0 if this item isn't attached to the tree. * Please note that even if this item has a non-zero parent, it can be still non viewable. * That is: the topmost parent of this item may be not attached to the viewable root. */ - Item * parent() const; + Item * parent() const; - /** + /** * Sets the parent for this item. You should also take care of inserting * this item in the parent's child list. */ - void setParent( Item *pParent ); + void setParent( Item *pParent ); - /** + /** * Returns the topmost parent item that is not a Root item (that is, is a Message or GroupHeader). */ - Item * topmostNonRoot(); + Item * topmostNonRoot(); - /** + /** * Returns the status associated to this Item. */ - const Akonadi::MessageStatus & status() const; + const Akonadi::MessageStatus & status() const; - /** + /** * Sets the status associated to this Item. */ - void setStatus( const Akonadi::MessageStatus &status ); + void setStatus( const Akonadi::MessageStatus &status ); - /** + /** * Returns a string describing the status e.g: "Read, Forwarded, Important" */ - QString statusDescription() const; + QString statusDescription() const; - /** + /** * Returns the size of this item (size of the Message, mainly) */ - size_t size() const; + size_t size() const; - /** + /** * Sets the size of this item (size of the Message, mainly) */ - void setSize( size_t size ); + void setSize( size_t size ); - /** + /** * A string with a text rappresentation of size(). This is computed on-the-fly * and not cached. */ - QString formattedSize() const; + QString formattedSize() const; - /** + /** * Returns the date of this item */ - time_t date() const; + time_t date() const; - /** + /** * Sets the date of this item */ - void setDate( time_t date ); + void setDate( time_t date ); - /** + /** * A string with a text rappresentation of date() obtained via Manager. This is computed on-the-fly * and not cached. */ - QString formattedDate() const; + QString formattedDate() const; - /** + /** * Returns the maximum date in the subtree originating from this item. * This is kept up-to-date by MessageList::Model. */ - time_t maxDate() const; + time_t maxDate() const; - /** + /** * Sets the maximum date in the subtree originating from this item. */ - void setMaxDate( time_t date ); + void setMaxDate( time_t date ); - /** + /** * A string with a text rappresentation of maxDate() obtained via Manager. This is computed on-the-fly * and not cached. */ - QString formattedMaxDate() const; + QString formattedMaxDate() const; - /** + /** * Recompute the maximum date from the current children list. * Return true if the current max date changed and false otherwise. */ - bool recomputeMaxDate(); + bool recomputeMaxDate(); - /** + /** * Returns the sender associated to this item. */ - const QString & sender() const; + const QString & sender() const; - /** + /** * Sets the sender associated to this item. */ - void setSender( const QString &sender ); + void setSender( const QString &sender ); - /** + /** * Returns the receiver associated to this item. */ - const QString & receiver() const; + const QString & receiver() const; - /** + /** * Sets the sender associated to this item. */ - void setReceiver( const QString &receiver ); + void setReceiver( const QString &receiver ); - /** + /** * Returns the sender or the receiver, depending on the underlying StorageModel settings. */ - const QString & senderOrReceiver() const; + const QString & senderOrReceiver() const; - /** + /** * Returns whether sender or receiver is supposed to be displayed. */ - bool useReceiver() const; + bool useReceiver() const; - /** + /** * Returns the subject associated to this Item. */ - const QString & subject() const; + const QString & subject() const; - /** + /** * Sets the subject associated to this Item. */ - void setSubject( const QString &subject ); + void setSubject( const QString &subject ); - /** + /** * This is meant to be called right after the constructor. * It sets up several items at once (so even if not inlined it's still a single call) * and it skips some calls that can be avoided at constructor time. */ - void initialSetup( time_t date, size_t size, - const QString &sender, - const QString &receiver, - bool useReceiver ); + void initialSetup( time_t date, size_t size, + const QString &sender, + const QString &receiver, + bool useReceiver ); - void setItemId(qint64 id); - qint64 itemId() const; + void setItemId(qint64 id); + qint64 itemId() const; - /** + /** * This is meant to be called right after the constructor for MessageItem objects. * It sets up several items at once (so even if not inlined it's still a single call). */ - void setSubjectAndStatus( const QString &subject, - const Akonadi::MessageStatus &status ); + void setSubjectAndStatus( const QString &subject, + const Akonadi::MessageStatus &status ); - /** + /** * Appends an Item to this item's child list. * The Model is used for beginInsertRows()/endInsertRows() calls. */ - int appendChildItem( Model *model, Item *child ); + int appendChildItem( Model *model, Item *child ); - /** + /** * Appends a child item without inserting it via the model. * This is useful in ThemeEditor which doesn't use a custom model for the items. * You shouldn't need to use this function... */ - void rawAppendChildItem( Item * child ); + void rawAppendChildItem( Item * child ); - /** + /** * Removes a child from this item's child list without deleting it. * The Model is used for beginRemoveRows()/endRemoveRows() calls. */ - void takeChildItem( Model *model, Item *child ); + void takeChildItem( Model *model, Item *child ); - /** + /** * Kills all the child items without emitting any signal, recursively. * It should be used only when MessageList::Model is reset() afterwards. */ - void killAllChildItems(); + void killAllChildItems(); protected: - ItemPrivate * const d_ptr; - Q_DECLARE_PRIVATE( Item ) + ItemPrivate * const d_ptr; + Q_DECLARE_PRIVATE( Item ) }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/manager.cpp kdepim-4.13.0/messagelist/core/manager.cpp --- kdepim-4.12.97/messagelist/core/manager.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/manager.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -55,370 +55,370 @@ Manager * Manager::mInstance = 0; Manager::Manager() - : QObject() + : QObject() { - mInstance = this; + mInstance = this; - mDateFormatter = new KMime::DateFormatter(); + mDateFormatter = new KMime::DateFormatter(); - mPixmapMessageNew = new QPixmap( SmallIcon( QLatin1String( "mail-unread-new" ) ) ); - mPixmapMessageUnread = new QPixmap( SmallIcon( QLatin1String( "mail-unread" ) ) ); - mPixmapMessageRead = new QPixmap( SmallIcon( QLatin1String( "mail-read" ) ) ); - mPixmapMessageDeleted = new QPixmap( SmallIcon( QLatin1String( "mail-deleted" ) ) ); - mPixmapMessageReplied = new QPixmap( SmallIcon( QLatin1String( "mail-replied" ) ) ); - mPixmapMessageRepliedAndForwarded = new QPixmap( SmallIcon( QLatin1String( "mail-forwarded-replied" ) ) ); - mPixmapMessageQueued = new QPixmap( SmallIcon( QLatin1String( "mail-queued" ) ) ); // mail-queue ? - mPixmapMessageActionItem = new QPixmap( SmallIcon( QLatin1String( "mail-task" ) ) ); - mPixmapMessageSent = new QPixmap( SmallIcon( QLatin1String( "mail-sent" ) ) ); - mPixmapMessageForwarded = new QPixmap( SmallIcon( QLatin1String( "mail-forwarded" ) ) ); - mPixmapMessageImportant = new QPixmap( SmallIcon( QLatin1String( "emblem-important" ) ) ); // "flag" - mPixmapMessageWatched = new QPixmap( KStandardDirs::locate( "data", QLatin1String( "messagelist/pics/mail-thread-watch.png" ) ) ); - mPixmapMessageIgnored = new QPixmap( KStandardDirs::locate( "data", QLatin1String( "messagelist/pics/mail-thread-ignored.png" ) ) ); - mPixmapMessageSpam = new QPixmap( SmallIcon( QLatin1String( "mail-mark-junk" ) ) ); - mPixmapMessageHam = new QPixmap( SmallIcon( QLatin1String( "mail-mark-notjunk" ) ) ); - mPixmapMessageFullySigned = new QPixmap( SmallIcon( QLatin1String( "mail-signed-verified" ) ) ); - mPixmapMessagePartiallySigned = new QPixmap( SmallIcon( QLatin1String( "mail-signed-part" ) ) ); - mPixmapMessageUndefinedSigned = new QPixmap( SmallIcon( QLatin1String( "mail-signed" ) ) ); - mPixmapMessageNotSigned = new QPixmap( SmallIcon( QLatin1String( "text-plain" ) ) ); - mPixmapMessageFullyEncrypted = new QPixmap( SmallIcon( QLatin1String( "mail-encrypted-full" ) ) ); - mPixmapMessagePartiallyEncrypted = new QPixmap( SmallIcon( QLatin1String( "mail-encrypted-part" ) ) ); - mPixmapMessageUndefinedEncrypted = new QPixmap( SmallIcon( QLatin1String( "mail-encrypted" ) ) ); - mPixmapMessageNotEncrypted = new QPixmap( SmallIcon( QLatin1String( "text-plain" ) ) ); - mPixmapMessageAttachment = new QPixmap( SmallIcon( QLatin1String( "mail-attachment" ) ) ); - mPixmapMessageAnnotation = new QPixmap( SmallIcon( QLatin1String( "view-pim-notes" ) ) ); - mPixmapMessageInvitation = new QPixmap( SmallIcon( QLatin1String( "mail-invitation" ) ) ); - if ( KApplication::isRightToLeft() ) - mPixmapShowMore = new QPixmap( SmallIcon( QLatin1String( "arrow-left" ) ) ); - else - mPixmapShowMore = new QPixmap( SmallIcon( QLatin1String( "arrow-right" ) ) ); - mPixmapShowLess = new QPixmap( SmallIcon( QLatin1String( "arrow-down" ) ) ); - mPixmapVerticalLine = new QPixmap( KStandardDirs::locate( "data", QLatin1String( "messagelist/pics/mail-vertical-separator-line.png" ) ) ); - mPixmapHorizontalSpacer = new QPixmap( KStandardDirs::locate( "data", QLatin1String( "messagelist/pics/mail-horizontal-space.png" ) ) ); - - mCachedLocalizedUnknownText = i18nc( "Unknown date", "Unknown" ) ; - - loadConfiguration(); - connect( Settings::self(), SIGNAL(configChanged()), - this, SLOT(reloadGlobalConfiguration()) ); + mPixmapMessageNew = new QPixmap( SmallIcon( QLatin1String( "mail-unread-new" ) ) ); + mPixmapMessageUnread = new QPixmap( SmallIcon( QLatin1String( "mail-unread" ) ) ); + mPixmapMessageRead = new QPixmap( SmallIcon( QLatin1String( "mail-read" ) ) ); + mPixmapMessageDeleted = new QPixmap( SmallIcon( QLatin1String( "mail-deleted" ) ) ); + mPixmapMessageReplied = new QPixmap( SmallIcon( QLatin1String( "mail-replied" ) ) ); + mPixmapMessageRepliedAndForwarded = new QPixmap( SmallIcon( QLatin1String( "mail-forwarded-replied" ) ) ); + mPixmapMessageQueued = new QPixmap( SmallIcon( QLatin1String( "mail-queued" ) ) ); // mail-queue ? + mPixmapMessageActionItem = new QPixmap( SmallIcon( QLatin1String( "mail-task" ) ) ); + mPixmapMessageSent = new QPixmap( SmallIcon( QLatin1String( "mail-sent" ) ) ); + mPixmapMessageForwarded = new QPixmap( SmallIcon( QLatin1String( "mail-forwarded" ) ) ); + mPixmapMessageImportant = new QPixmap( SmallIcon( QLatin1String( "emblem-important" ) ) ); // "flag" + mPixmapMessageWatched = new QPixmap( KStandardDirs::locate( "data", QLatin1String( "messagelist/pics/mail-thread-watch.png" ) ) ); + mPixmapMessageIgnored = new QPixmap( KStandardDirs::locate( "data", QLatin1String( "messagelist/pics/mail-thread-ignored.png" ) ) ); + mPixmapMessageSpam = new QPixmap( SmallIcon( QLatin1String( "mail-mark-junk" ) ) ); + mPixmapMessageHam = new QPixmap( SmallIcon( QLatin1String( "mail-mark-notjunk" ) ) ); + mPixmapMessageFullySigned = new QPixmap( SmallIcon( QLatin1String( "mail-signed-verified" ) ) ); + mPixmapMessagePartiallySigned = new QPixmap( SmallIcon( QLatin1String( "mail-signed-part" ) ) ); + mPixmapMessageUndefinedSigned = new QPixmap( SmallIcon( QLatin1String( "mail-signed" ) ) ); + mPixmapMessageNotSigned = new QPixmap( SmallIcon( QLatin1String( "text-plain" ) ) ); + mPixmapMessageFullyEncrypted = new QPixmap( SmallIcon( QLatin1String( "mail-encrypted-full" ) ) ); + mPixmapMessagePartiallyEncrypted = new QPixmap( SmallIcon( QLatin1String( "mail-encrypted-part" ) ) ); + mPixmapMessageUndefinedEncrypted = new QPixmap( SmallIcon( QLatin1String( "mail-encrypted" ) ) ); + mPixmapMessageNotEncrypted = new QPixmap( SmallIcon( QLatin1String( "text-plain" ) ) ); + mPixmapMessageAttachment = new QPixmap( SmallIcon( QLatin1String( "mail-attachment" ) ) ); + mPixmapMessageAnnotation = new QPixmap( SmallIcon( QLatin1String( "view-pim-notes" ) ) ); + mPixmapMessageInvitation = new QPixmap( SmallIcon( QLatin1String( "mail-invitation" ) ) ); + if ( KApplication::isRightToLeft() ) + mPixmapShowMore = new QPixmap( SmallIcon( QLatin1String( "arrow-left" ) ) ); + else + mPixmapShowMore = new QPixmap( SmallIcon( QLatin1String( "arrow-right" ) ) ); + mPixmapShowLess = new QPixmap( SmallIcon( QLatin1String( "arrow-down" ) ) ); + mPixmapVerticalLine = new QPixmap( KStandardDirs::locate( "data", QLatin1String( "messagelist/pics/mail-vertical-separator-line.png" ) ) ); + mPixmapHorizontalSpacer = new QPixmap( KStandardDirs::locate( "data", QLatin1String( "messagelist/pics/mail-horizontal-space.png" ) ) ); + + mCachedLocalizedUnknownText = i18nc( "Unknown date", "Unknown" ) ; + + loadConfiguration(); + connect( Settings::self(), SIGNAL(configChanged()), + this, SLOT(reloadGlobalConfiguration()) ); } Manager::~Manager() { - saveConfiguration(); - removeAllAggregations(); - removeAllThemes(); - - delete mPixmapMessageNew; - delete mPixmapMessageUnread; - delete mPixmapMessageRead; - delete mPixmapMessageDeleted; - delete mPixmapMessageReplied; - delete mPixmapMessageRepliedAndForwarded; - delete mPixmapMessageQueued; - delete mPixmapMessageActionItem; - delete mPixmapMessageSent; - delete mPixmapMessageForwarded; - delete mPixmapMessageImportant; // "flag" - delete mPixmapMessageWatched; - delete mPixmapMessageIgnored; - delete mPixmapMessageSpam; - delete mPixmapMessageHam; - delete mPixmapMessageFullySigned; - delete mPixmapMessagePartiallySigned; - delete mPixmapMessageUndefinedSigned; - delete mPixmapMessageNotSigned; - delete mPixmapMessageFullyEncrypted; - delete mPixmapMessagePartiallyEncrypted; - delete mPixmapMessageUndefinedEncrypted; - delete mPixmapMessageNotEncrypted; - delete mPixmapMessageAttachment; - delete mPixmapMessageAnnotation; - delete mPixmapMessageInvitation; - delete mPixmapShowMore; - delete mPixmapShowLess; - delete mPixmapVerticalLine; - delete mPixmapHorizontalSpacer; + saveConfiguration(); + removeAllAggregations(); + removeAllThemes(); + + delete mPixmapMessageNew; + delete mPixmapMessageUnread; + delete mPixmapMessageRead; + delete mPixmapMessageDeleted; + delete mPixmapMessageReplied; + delete mPixmapMessageRepliedAndForwarded; + delete mPixmapMessageQueued; + delete mPixmapMessageActionItem; + delete mPixmapMessageSent; + delete mPixmapMessageForwarded; + delete mPixmapMessageImportant; // "flag" + delete mPixmapMessageWatched; + delete mPixmapMessageIgnored; + delete mPixmapMessageSpam; + delete mPixmapMessageHam; + delete mPixmapMessageFullySigned; + delete mPixmapMessagePartiallySigned; + delete mPixmapMessageUndefinedSigned; + delete mPixmapMessageNotSigned; + delete mPixmapMessageFullyEncrypted; + delete mPixmapMessagePartiallyEncrypted; + delete mPixmapMessageUndefinedEncrypted; + delete mPixmapMessageNotEncrypted; + delete mPixmapMessageAttachment; + delete mPixmapMessageAnnotation; + delete mPixmapMessageInvitation; + delete mPixmapShowMore; + delete mPixmapShowLess; + delete mPixmapVerticalLine; + delete mPixmapHorizontalSpacer; - delete mDateFormatter; + delete mDateFormatter; - mInstance = 0; + mInstance = 0; } void Manager::registerWidget( Widget *pWidget ) { - if ( !mInstance ) - mInstance = new Manager(); + if ( !mInstance ) + mInstance = new Manager(); - mInstance->mWidgetList.append( pWidget ); + mInstance->mWidgetList.append( pWidget ); } void Manager::unregisterWidget( Widget *pWidget ) { - if ( !mInstance ) - { - qWarning("ERROR: MessageList::Manager::unregisterWidget() called when Manager::mInstance is 0"); - return; - } - - mInstance->mWidgetList.removeAll( pWidget ); - - if ( mInstance->mWidgetList.isEmpty() ) - { - delete mInstance; - mInstance = 0; - } + if ( !mInstance ) + { + qWarning("ERROR: MessageList::Manager::unregisterWidget() called when Manager::mInstance is 0"); + return; + } + + mInstance->mWidgetList.removeAll( pWidget ); + + if ( mInstance->mWidgetList.isEmpty() ) + { + delete mInstance; + mInstance = 0; + } } const Aggregation * Manager::aggregation( const QString &id ) { - Aggregation * opt = mAggregations.value( id ); - if ( opt ) - return opt; + Aggregation * opt = mAggregations.value( id ); + if ( opt ) + return opt; - return defaultAggregation(); + return defaultAggregation(); } const Aggregation * Manager::defaultAggregation() { - KConfigGroup conf( Settings::self()->config(), - MessageList::Util::storageModelAggregationsGroup() ); + KConfigGroup conf( Settings::self()->config(), + MessageList::Util::storageModelAggregationsGroup() ); - const QString aggregationId = conf.readEntry( QLatin1String( "DefaultSet" ), "" ); + const QString aggregationId = conf.readEntry( QLatin1String( "DefaultSet" ), "" ); - Aggregation * opt = 0; + Aggregation * opt = 0; - if ( !aggregationId.isEmpty() ) - opt = mAggregations.value( aggregationId ); + if ( !aggregationId.isEmpty() ) + opt = mAggregations.value( aggregationId ); - if ( opt ) - return opt; + if ( opt ) + return opt; - // try just the first one - QHash< QString, Aggregation * >::ConstIterator it = mAggregations.constBegin(); - if ( it != mAggregations.constEnd() ) - return *it; + // try just the first one + QHash< QString, Aggregation * >::ConstIterator it = mAggregations.constBegin(); + if ( it != mAggregations.constEnd() ) + return *it; - // aargh - createDefaultAggregations(); + // aargh + createDefaultAggregations(); - return *( mAggregations.constBegin() ); + return *( mAggregations.constBegin() ); } void Manager::saveAggregationForStorageModel( const Akonadi::Collection &col, const QString &id, bool storageUsesPrivateAggregation ) { - if ( !col.isValid() ) - return; - saveAggregationForStorageModel( QString::number( col.id() ), id, storageUsesPrivateAggregation ); + if ( !col.isValid() ) + return; + saveAggregationForStorageModel( QString::number( col.id() ), id, storageUsesPrivateAggregation ); } void Manager::saveAggregationForStorageModel( const StorageModel *storageModel, const QString &id, bool storageUsesPrivateAggregation ) { - saveAggregationForStorageModel( storageModel->id(), id, storageUsesPrivateAggregation ); + saveAggregationForStorageModel( storageModel->id(), id, storageUsesPrivateAggregation ); } void Manager::saveAggregationForStorageModel( const QString &modelId, const QString &id, bool storageUsesPrivateAggregation ) { - KConfigGroup conf( Settings::self()->config(), - MessageList::Util::storageModelAggregationsGroup() ); + KConfigGroup conf( Settings::self()->config(), + MessageList::Util::storageModelAggregationsGroup() ); - if ( storageUsesPrivateAggregation ) - conf.writeEntry( MessageList::Util::setForStorageModelConfigName().arg( modelId ), id ); - else - conf.deleteEntry( MessageList::Util::setForStorageModelConfigName().arg( modelId ) ); + if ( storageUsesPrivateAggregation ) + conf.writeEntry( MessageList::Util::setForStorageModelConfigName().arg( modelId ), id ); + else + conf.deleteEntry( MessageList::Util::setForStorageModelConfigName().arg( modelId ) ); - if ( !storageUsesPrivateAggregation ) - conf.writeEntry( QLatin1String( "DefaultSet" ), id ); + if ( !storageUsesPrivateAggregation ) + conf.writeEntry( QLatin1String( "DefaultSet" ), id ); } const Aggregation * Manager::aggregationForStorageModel( const Akonadi::Collection &col, bool *storageUsesPrivateAggregation ) { - Q_ASSERT( storageUsesPrivateAggregation ); + Q_ASSERT( storageUsesPrivateAggregation ); - *storageUsesPrivateAggregation = false; // this is by default + *storageUsesPrivateAggregation = false; // this is by default - if ( !col.isValid() ) - return defaultAggregation(); - return Manager::aggregationForStorageModel( QString::number( col.id() ), storageUsesPrivateAggregation ); + if ( !col.isValid() ) + return defaultAggregation(); + return Manager::aggregationForStorageModel( QString::number( col.id() ), storageUsesPrivateAggregation ); } const Aggregation * Manager::aggregationForStorageModel( const StorageModel *storageModel, bool *storageUsesPrivateAggregation ) { - Q_ASSERT( storageUsesPrivateAggregation ); + Q_ASSERT( storageUsesPrivateAggregation ); - *storageUsesPrivateAggregation = false; // this is by default + *storageUsesPrivateAggregation = false; // this is by default - if ( !storageModel ) - return defaultAggregation(); - return Manager::aggregationForStorageModel( storageModel->id(), storageUsesPrivateAggregation ); + if ( !storageModel ) + return defaultAggregation(); + return Manager::aggregationForStorageModel( storageModel->id(), storageUsesPrivateAggregation ); } const Aggregation * Manager::aggregationForStorageModel( const QString &storageId, bool *storageUsesPrivateAggregation ) { - KConfigGroup conf( Settings::self()->config(), - MessageList::Util::storageModelAggregationsGroup() ); + KConfigGroup conf( Settings::self()->config(), + MessageList::Util::storageModelAggregationsGroup() ); - const QString aggregationId = conf.readEntry( MessageList::Util::setForStorageModelConfigName().arg( storageId ), "" ); + const QString aggregationId = conf.readEntry( MessageList::Util::setForStorageModelConfigName().arg( storageId ), "" ); - Aggregation * opt = 0; + Aggregation * opt = 0; - if ( !aggregationId.isEmpty() ) - { - // a private aggregation was stored - opt = mAggregations.value( aggregationId ); - *storageUsesPrivateAggregation = ( opt != 0 ); - } + if ( !aggregationId.isEmpty() ) + { + // a private aggregation was stored + opt = mAggregations.value( aggregationId ); + *storageUsesPrivateAggregation = ( opt != 0 ); + } - if ( opt ) - return opt; + if ( opt ) + return opt; - // FIXME: If the storageModel is a mailing list, maybe suggest a mailing-list like preset... - // We could even try to guess if the storageModel is a mailing list + // FIXME: If the storageModel is a mailing list, maybe suggest a mailing-list like preset... + // We could even try to guess if the storageModel is a mailing list - return defaultAggregation(); + return defaultAggregation(); } void Manager::addAggregation( Aggregation *set ) { - Aggregation * old = mAggregations.value( set->id() ); - delete old; - mAggregations.insert( set->id(), set ); + Aggregation * old = mAggregations.value( set->id() ); + delete old; + mAggregations.insert( set->id(), set ); } void Manager::createDefaultAggregations() { - addAggregation( - new Aggregation( - i18n( "Current Activity, Threaded" ), - i18n( "This view uses smart date range groups. " \ - "Messages are threaded. " \ - "So for example, in \"Today\" you will find all the messages arrived today " \ - "and all the threads that have been active today." - ), - Aggregation::GroupByDateRange, - Aggregation::ExpandRecentGroups, - Aggregation::PerfectReferencesAndSubject, - Aggregation::MostRecentMessage, - Aggregation::ExpandThreadsWithUnreadOrImportantMessages, - Aggregation::FavorInteractivity, - true - ) - ); - - addAggregation( - new Aggregation( - i18n( "Current Activity, Flat" ), - i18n( "This view uses smart date range groups. " \ - "Messages are not threaded. " \ - "So for example, in \"Today\" you will simply find all the messages arrived today." - ), - Aggregation::GroupByDateRange, - Aggregation::ExpandRecentGroups, - Aggregation::NoThreading, - Aggregation::MostRecentMessage, - Aggregation::NeverExpandThreads, - Aggregation::FavorInteractivity, - true - ) - ); - - addAggregation( - new Aggregation( - i18n( "Activity by Date, Threaded" ), - i18n( "This view uses day-by-day groups. " \ - "Messages are threaded. " \ - "So for example, in \"Today\" you will find all the messages arrived today " \ - "and all the threads that have been active today." - ), - Aggregation::GroupByDate, - Aggregation::ExpandRecentGroups, - Aggregation::PerfectReferencesAndSubject, - Aggregation::MostRecentMessage, - Aggregation::ExpandThreadsWithUnreadOrImportantMessages, - Aggregation::FavorInteractivity, - true - ) - ); - - addAggregation( - new Aggregation( - i18n( "Activity by Date, Flat" ), - i18n( "This view uses day-by-day groups. " \ - "Messages are not threaded. " \ - "So for example, in \"Today\" you will simply find all the messages arrived today." - ), - Aggregation::GroupByDate, - Aggregation::ExpandRecentGroups, - Aggregation::NoThreading, - Aggregation::MostRecentMessage, - Aggregation::NeverExpandThreads, - Aggregation::FavorInteractivity, - true - ) - ); - - addAggregation( - new Aggregation( - i18n( "Standard Mailing List" ), - i18n( "This is a plain and old mailing list view: no groups and heavy threading." ), - Aggregation::NoGrouping, - Aggregation::NeverExpandGroups, - Aggregation::PerfectReferencesAndSubject, - Aggregation::TopmostMessage, - Aggregation::ExpandThreadsWithUnreadOrImportantMessages, - Aggregation::FavorInteractivity, - true - ) - ); - - addAggregation( - new Aggregation( - i18n( "Flat Date View" ), - i18n( "This is a plain and old list of messages sorted by date: no groups and no threading." \ - ), - Aggregation::NoGrouping, - Aggregation::NeverExpandGroups, - Aggregation::NoThreading, - Aggregation::TopmostMessage, - Aggregation::NeverExpandThreads, - Aggregation::FavorInteractivity, - true - - ) - ); + addAggregation( + new Aggregation( + i18n( "Current Activity, Threaded" ), + i18n( "This view uses smart date range groups. " \ + "Messages are threaded. " \ + "So for example, in \"Today\" you will find all the messages arrived today " \ + "and all the threads that have been active today." + ), + Aggregation::GroupByDateRange, + Aggregation::ExpandRecentGroups, + Aggregation::PerfectReferencesAndSubject, + Aggregation::MostRecentMessage, + Aggregation::ExpandThreadsWithUnreadOrImportantMessages, + Aggregation::FavorInteractivity, + true + ) + ); + + addAggregation( + new Aggregation( + i18n( "Current Activity, Flat" ), + i18n( "This view uses smart date range groups. " \ + "Messages are not threaded. " \ + "So for example, in \"Today\" you will simply find all the messages arrived today." + ), + Aggregation::GroupByDateRange, + Aggregation::ExpandRecentGroups, + Aggregation::NoThreading, + Aggregation::MostRecentMessage, + Aggregation::NeverExpandThreads, + Aggregation::FavorInteractivity, + true + ) + ); + + addAggregation( + new Aggregation( + i18n( "Activity by Date, Threaded" ), + i18n( "This view uses day-by-day groups. " \ + "Messages are threaded. " \ + "So for example, in \"Today\" you will find all the messages arrived today " \ + "and all the threads that have been active today." + ), + Aggregation::GroupByDate, + Aggregation::ExpandRecentGroups, + Aggregation::PerfectReferencesAndSubject, + Aggregation::MostRecentMessage, + Aggregation::ExpandThreadsWithUnreadOrImportantMessages, + Aggregation::FavorInteractivity, + true + ) + ); + + addAggregation( + new Aggregation( + i18n( "Activity by Date, Flat" ), + i18n( "This view uses day-by-day groups. " \ + "Messages are not threaded. " \ + "So for example, in \"Today\" you will simply find all the messages arrived today." + ), + Aggregation::GroupByDate, + Aggregation::ExpandRecentGroups, + Aggregation::NoThreading, + Aggregation::MostRecentMessage, + Aggregation::NeverExpandThreads, + Aggregation::FavorInteractivity, + true + ) + ); + + addAggregation( + new Aggregation( + i18n( "Standard Mailing List" ), + i18n( "This is a plain and old mailing list view: no groups and heavy threading." ), + Aggregation::NoGrouping, + Aggregation::NeverExpandGroups, + Aggregation::PerfectReferencesAndSubject, + Aggregation::TopmostMessage, + Aggregation::ExpandThreadsWithUnreadOrImportantMessages, + Aggregation::FavorInteractivity, + true + ) + ); + + addAggregation( + new Aggregation( + i18n( "Flat Date View" ), + i18n( "This is a plain and old list of messages sorted by date: no groups and no threading." \ + ), + Aggregation::NoGrouping, + Aggregation::NeverExpandGroups, + Aggregation::NoThreading, + Aggregation::TopmostMessage, + Aggregation::NeverExpandThreads, + Aggregation::FavorInteractivity, + true + + ) + ); + + addAggregation( + new Aggregation( + i18n( "Senders/Receivers, Flat" ), + i18n( "This view groups the messages by senders or receivers (depending on the folder " \ + "type). " \ + "Messages are not threaded." + ), + Aggregation::GroupBySenderOrReceiver, + Aggregation::NeverExpandGroups, + Aggregation::NoThreading, + Aggregation::TopmostMessage, + Aggregation::NeverExpandThreads, + Aggregation::FavorSpeed, + true + ) + ); + + addAggregation( + new Aggregation( + i18n( "Thread Starters" ), + i18n( "This view groups the messages in threads and then groups the threads by the starting user." ), + Aggregation::GroupBySenderOrReceiver, + Aggregation::NeverExpandGroups, + Aggregation::PerfectReferencesAndSubject, + Aggregation::TopmostMessage, + Aggregation::NeverExpandThreads, + Aggregation::FavorSpeed, + true + ) + ); - addAggregation( - new Aggregation( - i18n( "Senders/Receivers, Flat" ), - i18n( "This view groups the messages by senders or receivers (depending on the folder " \ - "type). " \ - "Messages are not threaded." - ), - Aggregation::GroupBySenderOrReceiver, - Aggregation::NeverExpandGroups, - Aggregation::NoThreading, - Aggregation::TopmostMessage, - Aggregation::NeverExpandThreads, - Aggregation::FavorSpeed, - true - ) - ); - - addAggregation( - new Aggregation( - i18n( "Thread Starters" ), - i18n( "This view groups the messages in threads and then groups the threads by the starting user." ), - Aggregation::GroupBySenderOrReceiver, - Aggregation::NeverExpandGroups, - Aggregation::PerfectReferencesAndSubject, - Aggregation::TopmostMessage, - Aggregation::NeverExpandThreads, - Aggregation::FavorSpeed, - true - ) - ); - -/* + /* FIX THIS addAggregation( new Aggregation( @@ -440,117 +440,117 @@ void Manager::removeAllAggregations() { - QHash< QString, Aggregation * >::ConstIterator end( mAggregations.constEnd() ); - for( QHash< QString, Aggregation * >::ConstIterator it = mAggregations.constBegin(); it != end; ++it ) - delete ( *it ); + QHash< QString, Aggregation * >::ConstIterator end( mAggregations.constEnd() ); + for( QHash< QString, Aggregation * >::ConstIterator it = mAggregations.constBegin(); it != end; ++it ) + delete ( *it ); - mAggregations.clear(); + mAggregations.clear(); } void Manager::aggregationsConfigurationCompleted() { - if ( mAggregations.isEmpty() ) - createDefaultAggregations(); // panic + if ( mAggregations.isEmpty() ) + createDefaultAggregations(); // panic - saveConfiguration(); // just to be sure :) + saveConfiguration(); // just to be sure :) - // notify all the widgets that they should reload the option set combos - emit aggregationsChanged(); + // notify all the widgets that they should reload the option set combos + emit aggregationsChanged(); } const SortOrder Manager::sortOrderForStorageModel( const StorageModel *storageModel, bool *storageUsesPrivateSortOrder ) { - Q_ASSERT( storageUsesPrivateSortOrder ); + Q_ASSERT( storageUsesPrivateSortOrder ); - *storageUsesPrivateSortOrder = false; // this is by default + *storageUsesPrivateSortOrder = false; // this is by default - if ( !storageModel ) - return SortOrder(); + if ( !storageModel ) + return SortOrder(); - KConfigGroup conf( Settings::self()->config(), MessageList::Util::storageModelSortOrderGroup() ); - SortOrder ret; - ret.readConfig( conf, storageModel->id(), storageUsesPrivateSortOrder ); - return ret; + KConfigGroup conf( Settings::self()->config(), MessageList::Util::storageModelSortOrderGroup() ); + SortOrder ret; + ret.readConfig( conf, storageModel->id(), storageUsesPrivateSortOrder ); + return ret; } void Manager::saveSortOrderForStorageModel( const StorageModel *storageModel, const SortOrder& order, bool storageUsesPrivateSortOrder ) { - KConfigGroup conf( Settings::self()->config(), MessageList::Util::storageModelSortOrderGroup() ); - order.writeConfig( conf, storageModel->id(), storageUsesPrivateSortOrder ); + KConfigGroup conf( Settings::self()->config(), MessageList::Util::storageModelSortOrderGroup() ); + order.writeConfig( conf, storageModel->id(), storageUsesPrivateSortOrder ); } const Theme * Manager::theme( const QString &id ) { - Theme * opt = mThemes.value( id ); - if ( opt ) - return opt; + Theme * opt = mThemes.value( id ); + if ( opt ) + return opt; - return defaultTheme(); + return defaultTheme(); } const Theme * Manager::defaultTheme() { - KConfigGroup conf( Settings::self()->config(), MessageList::Util::storageModelThemesGroup() ); + KConfigGroup conf( Settings::self()->config(), MessageList::Util::storageModelThemesGroup() ); - const QString themeId = conf.readEntry( QLatin1String( "DefaultSet" ), "" ); + const QString themeId = conf.readEntry( QLatin1String( "DefaultSet" ), "" ); - Theme * opt = 0; + Theme * opt = 0; - if ( !themeId.isEmpty() ) - opt = mThemes.value( themeId ); + if ( !themeId.isEmpty() ) + opt = mThemes.value( themeId ); - if ( opt ) - return opt; + if ( opt ) + return opt; - // try just the first one - QHash< QString, Theme * >::ConstIterator it = mThemes.constBegin(); - if ( it != mThemes.constEnd() ) - return *it; + // try just the first one + QHash< QString, Theme * >::ConstIterator it = mThemes.constBegin(); + if ( it != mThemes.constEnd() ) + return *it; - // aargh - createDefaultThemes(); + // aargh + createDefaultThemes(); - it = mThemes.constBegin(); + it = mThemes.constBegin(); - Q_ASSERT( it != mThemes.constEnd() ); + Q_ASSERT( it != mThemes.constEnd() ); - return *it; + return *it; } void Manager::saveThemeForStorageModel( int index, const QString &id, bool storageUsesPrivateTheme ) { - saveThemeForStorageModel( QString::number( index ), id, storageUsesPrivateTheme ); + saveThemeForStorageModel( QString::number( index ), id, storageUsesPrivateTheme ); } void Manager::saveThemeForStorageModel( const StorageModel *storageModel, const QString &id, bool storageUsesPrivateTheme ) { - saveThemeForStorageModel( storageModel->id(), id, storageUsesPrivateTheme ); + saveThemeForStorageModel( storageModel->id(), id, storageUsesPrivateTheme ); } void Manager::saveThemeForStorageModel( const QString &storageModelIndex, const QString &id, bool storageUsesPrivateTheme ) { - KConfigGroup conf( Settings::self()->config(), MessageList::Util::storageModelThemesGroup() ); + KConfigGroup conf( Settings::self()->config(), MessageList::Util::storageModelThemesGroup() ); - if ( storageUsesPrivateTheme ) - conf.writeEntry( MessageList::Util::setForStorageModelConfigName().arg( storageModelIndex ), id ); - else - conf.deleteEntry( MessageList::Util::setForStorageModelConfigName().arg( storageModelIndex ) ); + if ( storageUsesPrivateTheme ) + conf.writeEntry( MessageList::Util::setForStorageModelConfigName().arg( storageModelIndex ), id ); + else + conf.deleteEntry( MessageList::Util::setForStorageModelConfigName().arg( storageModelIndex ) ); - if ( !storageUsesPrivateTheme ) - conf.writeEntry( QLatin1String( "DefaultSet" ), id ); + if ( !storageUsesPrivateTheme ) + conf.writeEntry( QLatin1String( "DefaultSet" ), id ); } const Theme * Manager::themeForStorageModel( const Akonadi::Collection & col, bool * storageUsesPrivateTheme ) { - Q_ASSERT( storageUsesPrivateTheme ); + Q_ASSERT( storageUsesPrivateTheme ); - *storageUsesPrivateTheme = false; // this is by default + *storageUsesPrivateTheme = false; // this is by default - if ( !col.isValid() ) - return defaultTheme(); - return Manager::themeForStorageModel( QString::number( col.id() ), storageUsesPrivateTheme ); + if ( !col.isValid() ) + return defaultTheme(); + return Manager::themeForStorageModel( QString::number( col.id() ), storageUsesPrivateTheme ); } @@ -558,496 +558,496 @@ { - Q_ASSERT( storageUsesPrivateTheme ); + Q_ASSERT( storageUsesPrivateTheme ); - *storageUsesPrivateTheme = false; // this is by default + *storageUsesPrivateTheme = false; // this is by default - if ( !storageModel ) - return defaultTheme(); - return Manager::themeForStorageModel( storageModel->id(), storageUsesPrivateTheme ); + if ( !storageModel ) + return defaultTheme(); + return Manager::themeForStorageModel( storageModel->id(), storageUsesPrivateTheme ); } const Theme * Manager::themeForStorageModel( const QString &id, bool *storageUsesPrivateTheme ) { - KConfigGroup conf( Settings::self()->config(), MessageList::Util::storageModelThemesGroup() ); - const QString themeId = conf.readEntry( MessageList::Util::setForStorageModelConfigName().arg( id ), "" ); + KConfigGroup conf( Settings::self()->config(), MessageList::Util::storageModelThemesGroup() ); + const QString themeId = conf.readEntry( MessageList::Util::setForStorageModelConfigName().arg( id ), "" ); - Theme * opt = 0; + Theme * opt = 0; - if ( !themeId.isEmpty() ) - { - // a private theme was stored - opt = mThemes.value( themeId ); - *storageUsesPrivateTheme = (opt != 0); - } + if ( !themeId.isEmpty() ) + { + // a private theme was stored + opt = mThemes.value( themeId ); + *storageUsesPrivateTheme = (opt != 0); + } - if ( opt ) - return opt; + if ( opt ) + return opt; - // FIXME: If the storageModel is a mailing list, maybe suggest a mailing-list like preset... - // We could even try to guess if the storageModel is a mailing list + // FIXME: If the storageModel is a mailing list, maybe suggest a mailing-list like preset... + // We could even try to guess if the storageModel is a mailing list - // FIXME: Prefer right-to-left themes when application layout is RTL. + // FIXME: Prefer right-to-left themes when application layout is RTL. - return defaultTheme(); + return defaultTheme(); } void Manager::addTheme( Theme *set ) { - Theme * old = mThemes.value( set->id() ); - delete old; - mThemes.insert( set->id(), set ); + Theme * old = mThemes.value( set->id() ); + delete old; + mThemes.insert( set->id(), set ); } static Theme::Column * add_theme_simple_text_column( Theme * s, const QString &name, Theme::ContentItem::Type type, bool visibleByDefault, SortOrder::MessageSorting messageSorting, bool alignRight, bool addGroupHeaderItem ) { - Theme::Column * c = new Theme::Column(); - c->setLabel( name ); - c->setVisibleByDefault( visibleByDefault ); - c->setMessageSorting( messageSorting ); - - Theme::Row * r = new Theme::Row(); - - Theme::ContentItem * i = new Theme::ContentItem( type ); - i->setFont( KGlobalSettings::generalFont() ); + Theme::Column * c = new Theme::Column(); + c->setLabel( name ); + c->setVisibleByDefault( visibleByDefault ); + c->setMessageSorting( messageSorting ); - if ( alignRight ) - r->addRightItem( i ); - else - r->addLeftItem( i ); - - c->addMessageRow( r ); - - if ( addGroupHeaderItem ) - { Theme::Row * r = new Theme::Row(); Theme::ContentItem * i = new Theme::ContentItem( type ); i->setFont( KGlobalSettings::generalFont() ); if ( alignRight ) - r->addRightItem( i ); + r->addRightItem( i ); else - r->addLeftItem( i ); + r->addLeftItem( i ); - c->addGroupHeaderRow( r ); - } + c->addMessageRow( r ); + if ( addGroupHeaderItem ) + { + Theme::Row * r = new Theme::Row(); + + Theme::ContentItem * i = new Theme::ContentItem( type ); + i->setFont( KGlobalSettings::generalFont() ); + + if ( alignRight ) + r->addRightItem( i ); + else + r->addLeftItem( i ); + + c->addGroupHeaderRow( r ); + } - s->addColumn( c ); - return c; + s->addColumn( c ); + + return c; } static Theme::Column * add_theme_simple_icon_column( Theme * s, const QString &name, const QString &pixmapName, Theme::ContentItem::Type type, bool visibleByDefault, SortOrder::MessageSorting messageSorting ) { - Theme::Column * c = new Theme::Column(); - c->setLabel( name ); - c->setPixmapName( pixmapName ); - c->setVisibleByDefault( visibleByDefault ); - c->setMessageSorting( messageSorting ); + Theme::Column * c = new Theme::Column(); + c->setLabel( name ); + c->setPixmapName( pixmapName ); + c->setVisibleByDefault( visibleByDefault ); + c->setMessageSorting( messageSorting ); - Theme::Row * r = new Theme::Row(); + Theme::Row * r = new Theme::Row(); - Theme::ContentItem * i = new Theme::ContentItem( type ); - i->setSoftenByBlendingWhenDisabled( true ); + Theme::ContentItem * i = new Theme::ContentItem( type ); + i->setSoftenByBlendingWhenDisabled( true ); - r->addLeftItem( i ); + r->addLeftItem( i ); - c->addMessageRow( r ); + c->addMessageRow( r ); - s->addColumn( c ); + s->addColumn( c ); - return c; + return c; } void Manager::createDefaultThemes() { - Theme * s; - Theme::Column * c; - Theme::Row * r; - Theme::ContentItem * i; - - // The "Classic" backward compatible theme - - s = new Theme( - i18nc( "Default theme name", "Classic" ), - i18n( "A simple, backward compatible, single row theme" ), true /*readOnly*/ - ); + Theme * s; + Theme::Column * c; + Theme::Row * r; + Theme::ContentItem * i; + + // The "Classic" backward compatible theme + + s = new Theme( + i18nc( "Default theme name", "Classic" ), + i18n( "A simple, backward compatible, single row theme" ), true /*readOnly*/ + ); c = new Theme::Column(); c->setLabel( i18nc( "@title:column Subject of messages", "Subject" ) ); c->setMessageSorting( SortOrder::SortMessagesBySubject ); - r = new Theme::Row(); - i = new Theme::ContentItem( Theme::ContentItem::ExpandedStateIcon ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::GroupHeaderLabel ); - QFont bigFont = KGlobalSettings::generalFont(); - bigFont.setBold( true ); - i->setFont( bigFont ); - i->setUseCustomFont( true ); - r->addLeftItem( i ); + r = new Theme::Row(); + i = new Theme::ContentItem( Theme::ContentItem::ExpandedStateIcon ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::GroupHeaderLabel ); + QFont bigFont = KGlobalSettings::generalFont(); + bigFont.setBold( true ); + i->setFont( bigFont ); + i->setUseCustomFont( true ); + r->addLeftItem( i ); c->addGroupHeaderRow( r ); - r = new Theme::Row(); - i = new Theme::ContentItem( Theme::ContentItem::CombinedReadRepliedStateIcon ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::AttachmentStateIcon ); - i->setHideWhenDisabled( true ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::AnnotationIcon ); - i->setHideWhenDisabled( true ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::InvitationIcon ); - i->setHideWhenDisabled( true ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::SignatureStateIcon ); - i->setHideWhenDisabled( true ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::EncryptionStateIcon ); - i->setHideWhenDisabled( true ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::Subject ); - r->addLeftItem( i ); + r = new Theme::Row(); + i = new Theme::ContentItem( Theme::ContentItem::CombinedReadRepliedStateIcon ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::AttachmentStateIcon ); + i->setHideWhenDisabled( true ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::AnnotationIcon ); + i->setHideWhenDisabled( true ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::InvitationIcon ); + i->setHideWhenDisabled( true ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::SignatureStateIcon ); + i->setHideWhenDisabled( true ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::EncryptionStateIcon ); + i->setHideWhenDisabled( true ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::Subject ); + r->addLeftItem( i ); c->addMessageRow( r ); - s->addColumn( c ); + s->addColumn( c ); - c = add_theme_simple_text_column( s, i18n( "Sender/Receiver" ), Theme::ContentItem::SenderOrReceiver, true, SortOrder::SortMessagesBySenderOrReceiver, false, false); - c->setIsSenderOrReceiver( true ); - add_theme_simple_text_column( s, i18nc( "Sender of a message", "Sender" ), Theme::ContentItem::Sender, false, SortOrder::SortMessagesBySender, false, false ); - add_theme_simple_text_column( s, i18nc( "Receiver of a message", "Receiver" ), Theme::ContentItem::Receiver, false, SortOrder::SortMessagesByReceiver, false, false ); - add_theme_simple_text_column( s, i18nc( "Date of a message", "Date" ), Theme::ContentItem::Date, true, SortOrder::SortMessagesByDateTime, false, false ); - add_theme_simple_text_column( s, i18n( "Most Recent Date" ), Theme::ContentItem::MostRecentDate, false, SortOrder::SortMessagesByDateTimeOfMostRecent, false, true ); - add_theme_simple_text_column( s, i18nc( "Size of a message", "Size" ), Theme::ContentItem::Size, false, SortOrder::SortMessagesBySize, false, false ); - add_theme_simple_icon_column( s, i18nc( "Attachement indication", "Attachment" ), QLatin1String( "mail-attachment" ), Theme::ContentItem::AttachmentStateIcon, false, SortOrder::NoMessageSorting ); - add_theme_simple_icon_column( s, i18n( "Read/Unread" ), QLatin1String( "mail-unread-new" ), Theme::ContentItem::ReadStateIcon, false, SortOrder::SortMessagesByUnreadStatus ); - add_theme_simple_icon_column( s, i18n( "Replied" ), QLatin1String( "mail-replied" ), Theme::ContentItem::RepliedStateIcon, false, SortOrder::NoMessageSorting ); - add_theme_simple_icon_column( s, i18nc( "Message importance indication", "Important" ), QLatin1String( "emblem-important" ), Theme::ContentItem::ImportantStateIcon, false, SortOrder::SortMessagesByImportantStatus ); - add_theme_simple_icon_column( s, i18n( "Action Item" ), QLatin1String( "mail-task" ), Theme::ContentItem::ActionItemStateIcon, false, SortOrder::SortMessagesByActionItemStatus ); - add_theme_simple_icon_column( s, i18n( "Spam/Ham" ), QLatin1String( "mail-mark-junk" ), Theme::ContentItem::SpamHamStateIcon, false, SortOrder::NoMessageSorting ); - add_theme_simple_icon_column( s, i18n( "Watched/Ignored" ), QLatin1String( "mail-thread-watch" ), Theme::ContentItem::WatchedIgnoredStateIcon, false, SortOrder::NoMessageSorting ); - add_theme_simple_icon_column( s, i18n( "Encryption" ), QLatin1String( "mail-encrypted-full" ), Theme::ContentItem::EncryptionStateIcon, false, SortOrder::NoMessageSorting ); - add_theme_simple_icon_column( s, i18n( "Signature" ), QLatin1String( "mail-signed-verified" ), Theme::ContentItem::SignatureStateIcon, false, SortOrder::NoMessageSorting ); - add_theme_simple_icon_column( s, i18n( "Tag List" ), QLatin1String( "feed-subscribe" ), Theme::ContentItem::TagList, false, SortOrder::NoMessageSorting ); - - s->resetColumnState(); // so it's initially set from defaults - - addTheme( s ); - - // The Fancy theme - - s = new Theme( - i18n( "Smart" ), - i18n( "A smart multiline and multi item theme" ), true /*readOnly*/ - ); + c = add_theme_simple_text_column( s, i18n( "Sender/Receiver" ), Theme::ContentItem::SenderOrReceiver, true, SortOrder::SortMessagesBySenderOrReceiver, false, false); + c->setIsSenderOrReceiver( true ); + add_theme_simple_text_column( s, i18nc( "Sender of a message", "Sender" ), Theme::ContentItem::Sender, false, SortOrder::SortMessagesBySender, false, false ); + add_theme_simple_text_column( s, i18nc( "Receiver of a message", "Receiver" ), Theme::ContentItem::Receiver, false, SortOrder::SortMessagesByReceiver, false, false ); + add_theme_simple_text_column( s, i18nc( "Date of a message", "Date" ), Theme::ContentItem::Date, true, SortOrder::SortMessagesByDateTime, false, false ); + add_theme_simple_text_column( s, i18n( "Most Recent Date" ), Theme::ContentItem::MostRecentDate, false, SortOrder::SortMessagesByDateTimeOfMostRecent, false, true ); + add_theme_simple_text_column( s, i18nc( "Size of a message", "Size" ), Theme::ContentItem::Size, false, SortOrder::SortMessagesBySize, false, false ); + add_theme_simple_icon_column( s, i18nc( "Attachement indication", "Attachment" ), QLatin1String( "mail-attachment" ), Theme::ContentItem::AttachmentStateIcon, false, SortOrder::NoMessageSorting ); + add_theme_simple_icon_column( s, i18n( "Read/Unread" ), QLatin1String( "mail-unread-new" ), Theme::ContentItem::ReadStateIcon, false, SortOrder::SortMessagesByUnreadStatus ); + add_theme_simple_icon_column( s, i18n( "Replied" ), QLatin1String( "mail-replied" ), Theme::ContentItem::RepliedStateIcon, false, SortOrder::NoMessageSorting ); + add_theme_simple_icon_column( s, i18nc( "Message importance indication", "Important" ), QLatin1String( "emblem-important" ), Theme::ContentItem::ImportantStateIcon, false, SortOrder::SortMessagesByImportantStatus ); + add_theme_simple_icon_column( s, i18n( "Action Item" ), QLatin1String( "mail-task" ), Theme::ContentItem::ActionItemStateIcon, false, SortOrder::SortMessagesByActionItemStatus ); + add_theme_simple_icon_column( s, i18n( "Spam/Ham" ), QLatin1String( "mail-mark-junk" ), Theme::ContentItem::SpamHamStateIcon, false, SortOrder::NoMessageSorting ); + add_theme_simple_icon_column( s, i18n( "Watched/Ignored" ), QLatin1String( "mail-thread-watch" ), Theme::ContentItem::WatchedIgnoredStateIcon, false, SortOrder::NoMessageSorting ); + add_theme_simple_icon_column( s, i18n( "Encryption" ), QLatin1String( "mail-encrypted-full" ), Theme::ContentItem::EncryptionStateIcon, false, SortOrder::NoMessageSorting ); + add_theme_simple_icon_column( s, i18n( "Signature" ), QLatin1String( "mail-signed-verified" ), Theme::ContentItem::SignatureStateIcon, false, SortOrder::NoMessageSorting ); + add_theme_simple_icon_column( s, i18n( "Tag List" ), QLatin1String( "feed-subscribe" ), Theme::ContentItem::TagList, false, SortOrder::NoMessageSorting ); + + s->resetColumnState(); // so it's initially set from defaults + + addTheme( s ); + + // The Fancy theme + + s = new Theme( + i18n( "Smart" ), + i18n( "A smart multiline and multi item theme" ), true /*readOnly*/ + ); c = new Theme::Column(); c->setLabel( i18n( "Message" ) ); - r = new Theme::Row(); - i = new Theme::ContentItem( Theme::ContentItem::ExpandedStateIcon ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::GroupHeaderLabel ); - QFont aBigFont = KGlobalSettings::generalFont(); - aBigFont.setBold( true ); - i->setFont( aBigFont ); - i->setUseCustomFont( true ); - r->addLeftItem( i ); + r = new Theme::Row(); + i = new Theme::ContentItem( Theme::ContentItem::ExpandedStateIcon ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::GroupHeaderLabel ); + QFont aBigFont = KGlobalSettings::generalFont(); + aBigFont.setBold( true ); + i->setFont( aBigFont ); + i->setUseCustomFont( true ); + r->addLeftItem( i ); c->addGroupHeaderRow( r ); - r = new Theme::Row(); - i = new Theme::ContentItem( Theme::ContentItem::Subject ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::ReadStateIcon ); - r->addRightItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::RepliedStateIcon ); - i->setHideWhenDisabled( true ); - r->addRightItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::AttachmentStateIcon ); - i->setHideWhenDisabled( true ); - r->addRightItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::AnnotationIcon ); - i->setHideWhenDisabled( true ); - r->addRightItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::InvitationIcon ); - i->setHideWhenDisabled( true ); - r->addRightItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::EncryptionStateIcon ); - i->setHideWhenDisabled( true ); - r->addRightItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::SignatureStateIcon ); - i->setHideWhenDisabled( true ); - r->addRightItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::TagList ); - i->setHideWhenDisabled( true ); - r->addRightItem( i ); + r = new Theme::Row(); + i = new Theme::ContentItem( Theme::ContentItem::Subject ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::ReadStateIcon ); + r->addRightItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::RepliedStateIcon ); + i->setHideWhenDisabled( true ); + r->addRightItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::AttachmentStateIcon ); + i->setHideWhenDisabled( true ); + r->addRightItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::AnnotationIcon ); + i->setHideWhenDisabled( true ); + r->addRightItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::InvitationIcon ); + i->setHideWhenDisabled( true ); + r->addRightItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::EncryptionStateIcon ); + i->setHideWhenDisabled( true ); + r->addRightItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::SignatureStateIcon ); + i->setHideWhenDisabled( true ); + r->addRightItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::TagList ); + i->setHideWhenDisabled( true ); + r->addRightItem( i ); c->addMessageRow( r ); - Theme::Row * firstFancyRow = r; // save it so we can continue adding stuff below (after cloning the theme) + Theme::Row * firstFancyRow = r; // save it so we can continue adding stuff below (after cloning the theme) - r = new Theme::Row(); - i = new Theme::ContentItem( Theme::ContentItem::SenderOrReceiver ); - i->setSoftenByBlending( true ); - QFont aItalicFont = KGlobalSettings::generalFont(); - aItalicFont.setItalic( true ); - i->setFont( aItalicFont ); - i->setUseCustomFont( true ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::Date ); - i->setSoftenByBlending( true ); - i->setFont( aItalicFont ); - i->setUseCustomFont( true ); - r->addRightItem( i ); + r = new Theme::Row(); + i = new Theme::ContentItem( Theme::ContentItem::SenderOrReceiver ); + i->setSoftenByBlending( true ); + QFont aItalicFont = KGlobalSettings::generalFont(); + aItalicFont.setItalic( true ); + i->setFont( aItalicFont ); + i->setUseCustomFont( true ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::Date ); + i->setSoftenByBlending( true ); + i->setFont( aItalicFont ); + i->setUseCustomFont( true ); + r->addRightItem( i ); c->addMessageRow( r ); - s->addColumn( c ); + s->addColumn( c ); - // clone the "Fancy theme" here so we'll use it as starting point for the "Fancy with clickable status" - Theme * fancyWithClickableStatus = new Theme( *s ); - fancyWithClickableStatus->detach(); - fancyWithClickableStatus->generateUniqueId(); + // clone the "Fancy theme" here so we'll use it as starting point for the "Fancy with clickable status" + Theme * fancyWithClickableStatus = new Theme( *s ); + fancyWithClickableStatus->detach(); + fancyWithClickableStatus->generateUniqueId(); - // and continue the "Fancy" specific settings - r = firstFancyRow; + // and continue the "Fancy" specific settings + r = firstFancyRow; - i = new Theme::ContentItem( Theme::ContentItem::ActionItemStateIcon ); - i->setHideWhenDisabled( true ); - r->addRightItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::ImportantStateIcon ); - i->setHideWhenDisabled( true ); - r->addRightItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::SpamHamStateIcon ); - i->setHideWhenDisabled( true ); - r->addRightItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::WatchedIgnoredStateIcon ); - i->setHideWhenDisabled( true ); - r->addRightItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::ActionItemStateIcon ); + i->setHideWhenDisabled( true ); + r->addRightItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::ImportantStateIcon ); + i->setHideWhenDisabled( true ); + r->addRightItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::SpamHamStateIcon ); + i->setHideWhenDisabled( true ); + r->addRightItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::WatchedIgnoredStateIcon ); + i->setHideWhenDisabled( true ); + r->addRightItem( i ); - s->setViewHeaderPolicy( Theme::NeverShowHeader ); + s->setViewHeaderPolicy( Theme::NeverShowHeader ); - s->resetColumnState(); // so it's initially set from defaults + s->resetColumnState(); // so it's initially set from defaults - addTheme( s ); + addTheme( s ); - // The "Fancy with Clickable Status" theme + // The "Fancy with Clickable Status" theme - s = fancyWithClickableStatus; + s = fancyWithClickableStatus; - s->setName( i18n( "Smart with Clickable Status" ) ); - s->setDescription( i18n( "A smart multiline and multi item theme with a clickable status column" ) ); - s->setReadOnly( true ); + s->setName( i18n( "Smart with Clickable Status" ) ); + s->setDescription( i18n( "A smart multiline and multi item theme with a clickable status column" ) ); + s->setReadOnly( true ); c = new Theme::Column(); c->setLabel( i18n( "Status" ) ); c->setVisibleByDefault( true ); - r = new Theme::Row(); - i = new Theme::ContentItem( Theme::ContentItem::ActionItemStateIcon ); - i->setSoftenByBlendingWhenDisabled( true ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::ImportantStateIcon ); - i->setSoftenByBlendingWhenDisabled( true ); - r->addLeftItem( i ); + r = new Theme::Row(); + i = new Theme::ContentItem( Theme::ContentItem::ActionItemStateIcon ); + i->setSoftenByBlendingWhenDisabled( true ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::ImportantStateIcon ); + i->setSoftenByBlendingWhenDisabled( true ); + r->addLeftItem( i ); c->addMessageRow( r ); - r = new Theme::Row(); - i = new Theme::ContentItem( Theme::ContentItem::SpamHamStateIcon ); - i->setSoftenByBlendingWhenDisabled( true ); - r->addLeftItem( i ); - i = new Theme::ContentItem( Theme::ContentItem::WatchedIgnoredStateIcon ); - i->setSoftenByBlendingWhenDisabled( true ); - r->addLeftItem( i ); + r = new Theme::Row(); + i = new Theme::ContentItem( Theme::ContentItem::SpamHamStateIcon ); + i->setSoftenByBlendingWhenDisabled( true ); + r->addLeftItem( i ); + i = new Theme::ContentItem( Theme::ContentItem::WatchedIgnoredStateIcon ); + i->setSoftenByBlendingWhenDisabled( true ); + r->addLeftItem( i ); c->addMessageRow( r ); - s->addColumn( c ); + s->addColumn( c ); - s->resetColumnState(); // so it's initially set from defaults + s->resetColumnState(); // so it's initially set from defaults - addTheme( s ); + addTheme( s ); } void Manager::removeAllThemes() { - QHash< QString, Theme * >::ConstIterator end( mThemes.constEnd() ); - for( QHash< QString, Theme * >::ConstIterator it = mThemes.constBegin(); it != end; ++it ) - delete ( *it ); + QHash< QString, Theme * >::ConstIterator end( mThemes.constEnd() ); + for( QHash< QString, Theme * >::ConstIterator it = mThemes.constBegin(); it != end; ++it ) + delete ( *it ); - mThemes.clear(); + mThemes.clear(); } void Manager::themesConfigurationCompleted() { - if ( mThemes.isEmpty() ) - createDefaultThemes(); // panic + if ( mThemes.isEmpty() ) + createDefaultThemes(); // panic - saveConfiguration(); // just to be sure :) + saveConfiguration(); // just to be sure :) - // notify all the widgets that they should reload the option set combos - emit themesChanged(); + // notify all the widgets that they should reload the option set combos + emit themesChanged(); } void Manager::reloadAllWidgets() { - QList< Widget * >::ConstIterator end( mWidgetList.constEnd() ); - for( QList< Widget * >::ConstIterator it = mWidgetList.constBegin(); it != end; ++it ) - { - if ( ( *it )->view() ) - ( *it )->view()->reload(); - } + QList< Widget * >::ConstIterator end( mWidgetList.constEnd() ); + for( QList< Widget * >::ConstIterator it = mWidgetList.constBegin(); it != end; ++it ) + { + if ( ( *it )->view() ) + ( *it )->view()->reload(); + } } void Manager::reloadGlobalConfiguration() { - // This is called when configuration changes (probably edited by the options dialog) - const int oldDateFormat = (int)mDateFormatter->format(); - const QString oldDateCustomFormat = mDateFormatter->customFormat(); - - loadGlobalConfiguration(); - - if ( - ( oldDateFormat != (int)mDateFormatter->format() ) || - ( oldDateCustomFormat != mDateFormatter->customFormat() ) - ) - reloadAllWidgets(); + // This is called when configuration changes (probably edited by the options dialog) + const int oldDateFormat = (int)mDateFormatter->format(); + const QString oldDateCustomFormat = mDateFormatter->customFormat(); + + loadGlobalConfiguration(); + + if ( + ( oldDateFormat != (int)mDateFormatter->format() ) || + ( oldDateCustomFormat != mDateFormatter->customFormat() ) + ) + reloadAllWidgets(); } void Manager::loadGlobalConfiguration() { - // Load the date format - const KMime::DateFormatter::FormatType type = static_cast( - MessageCore::GlobalSettings::self()->dateFormat() ); - mDateFormatter->setCustomFormat( MessageCore::GlobalSettings::self()->customDateFormat() ); - mDateFormatter->setFormat( type ); + // Load the date format + const KMime::DateFormatter::FormatType type = static_cast( + MessageCore::GlobalSettings::self()->dateFormat() ); + mDateFormatter->setCustomFormat( MessageCore::GlobalSettings::self()->customDateFormat() ); + mDateFormatter->setFormat( type ); } void Manager::loadConfiguration() { - loadGlobalConfiguration(); + loadGlobalConfiguration(); - { - // load Aggregations + { + // load Aggregations - KConfigGroup conf( Settings::self()->config(), "MessageListView::Aggregations" ); + KConfigGroup conf( Settings::self()->config(), "MessageListView::Aggregations" ); - mAggregations.clear(); + mAggregations.clear(); - const int cnt = conf.readEntry( "Count", 0 ); + const int cnt = conf.readEntry( "Count", 0 ); - int idx = 0; - while ( idx < cnt ) - { - const QString data = conf.readEntry( QString::fromLatin1( "Set%1" ).arg( idx ), QString() ); - if ( !data.isEmpty() ) - { - Aggregation * set = new Aggregation(); - if ( set->loadFromString( data ) ) + int idx = 0; + while ( idx < cnt ) { - if ( Aggregation * old = mAggregations.value( set->id() ) ) - delete old; - mAggregations.insert( set->id(), set ); - } else { - delete set; // b0rken + const QString data = conf.readEntry( QString::fromLatin1( "Set%1" ).arg( idx ), QString() ); + if ( !data.isEmpty() ) + { + Aggregation * set = new Aggregation(); + if ( set->loadFromString( data ) ) + { + if ( Aggregation * old = mAggregations.value( set->id() ) ) + delete old; + mAggregations.insert( set->id(), set ); + } else { + delete set; // b0rken + } + } + idx++; } - } - idx++; - } - if ( mAggregations.isEmpty() ) - { - // don't allow zero configuration, create some presets - createDefaultAggregations(); + if ( mAggregations.isEmpty() ) + { + // don't allow zero configuration, create some presets + createDefaultAggregations(); + } } - } - { - // load Themes + { + // load Themes - KConfigGroup conf( Settings::self()->config(), "MessageListView::Themes" ); + KConfigGroup conf( Settings::self()->config(), "MessageListView::Themes" ); - mThemes.clear(); + mThemes.clear(); - const int cnt = conf.readEntry( "Count", 0 ); + const int cnt = conf.readEntry( "Count", 0 ); - int idx = 0; - while ( idx < cnt ) - { - const QString data = conf.readEntry( QString::fromLatin1( "Set%1" ).arg( idx ), QString() ); - if ( !data.isEmpty() ) - { - Theme * set = new Theme(); - if ( set->loadFromString( data ) ) + int idx = 0; + while ( idx < cnt ) { - if ( Theme * old = mThemes.value( set->id() ) ) - delete old; - mThemes.insert( set->id(), set ); - } else { - kWarning() << "Saved theme loading failed"; - delete set; // b0rken + const QString data = conf.readEntry( QString::fromLatin1( "Set%1" ).arg( idx ), QString() ); + if ( !data.isEmpty() ) + { + Theme * set = new Theme(); + if ( set->loadFromString( data ) ) + { + if ( Theme * old = mThemes.value( set->id() ) ) + delete old; + mThemes.insert( set->id(), set ); + } else { + kWarning() << "Saved theme loading failed"; + delete set; // b0rken + } + } + ++idx; } - } - ++idx; - } - if ( mThemes.isEmpty() ) - { - // don't allow zero configuration, create some presets - createDefaultThemes(); + if ( mThemes.isEmpty() ) + { + // don't allow zero configuration, create some presets + createDefaultThemes(); + } } - } } void Manager::saveGlobalConfiguration() { - Settings::self()->writeConfig(); + Settings::self()->writeConfig(); } void Manager::saveConfiguration() { - saveGlobalConfiguration(); + saveGlobalConfiguration(); - { - // store aggregations + { + // store aggregations - KConfigGroup conf( Settings::self()->config(), "MessageListView::Aggregations" ); - //conf.clear(); + KConfigGroup conf( Settings::self()->config(), "MessageListView::Aggregations" ); + //conf.clear(); - conf.writeEntry( "Count", mAggregations.count() ); + conf.writeEntry( "Count", mAggregations.count() ); - int idx = 0; - QHash< QString, Aggregation * >::ConstIterator end( mAggregations.end() ); - for( QHash< QString, Aggregation * >::ConstIterator it = mAggregations.constBegin(); it != end; ++it ) - { - conf.writeEntry( QString::fromLatin1( "Set%1" ).arg( idx ), ( *it )->saveToString() ); - ++idx; + int idx = 0; + QHash< QString, Aggregation * >::ConstIterator end( mAggregations.end() ); + for( QHash< QString, Aggregation * >::ConstIterator it = mAggregations.constBegin(); it != end; ++it ) + { + conf.writeEntry( QString::fromLatin1( "Set%1" ).arg( idx ), ( *it )->saveToString() ); + ++idx; + } } - } - { - // store themes + { + // store themes - KConfigGroup conf( Settings::self()->config(), "MessageListView::Themes" ); - //conf.clear(); + KConfigGroup conf( Settings::self()->config(), "MessageListView::Themes" ); + //conf.clear(); - conf.writeEntry( "Count", mThemes.count() ); + conf.writeEntry( "Count", mThemes.count() ); - int idx = 0; - QHash< QString, Theme * >::ConstIterator end( mThemes.constEnd() ); - for( QHash< QString, Theme * >::ConstIterator it = mThemes.constBegin(); it != end; ++it ) - { - conf.writeEntry( QString::fromLatin1( "Set%1" ).arg( idx ), ( *it )->saveToString() ); - ++idx; + int idx = 0; + QHash< QString, Theme * >::ConstIterator end( mThemes.constEnd() ); + for( QHash< QString, Theme * >::ConstIterator it = mThemes.constBegin(); it != end; ++it ) + { + conf.writeEntry( QString::fromLatin1( "Set%1" ).arg( idx ), ( *it )->saveToString() ); + ++idx; + } } - } - Settings::self()->config()->sync(); + Settings::self()->config()->sync(); } diff -Nru kdepim-4.12.97/messagelist/core/manager.h kdepim-4.13.0/messagelist/core/manager.h --- kdepim-4.12.97/messagelist/core/manager.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/manager.h 2014-04-10 07:40:20.000000000 +0000 @@ -32,7 +32,7 @@ namespace KMime { - class DateFormatter; +class DateFormatter; } namespace MessageList @@ -60,213 +60,213 @@ */ class Manager : public QObject { - Q_OBJECT + Q_OBJECT protected: - explicit Manager(); - ~Manager(); + explicit Manager(); + ~Manager(); private: - static Manager * mInstance; - QList< Widget * > mWidgetList; - QHash< QString, Aggregation * > mAggregations; - QHash< QString, Theme * > mThemes; - KMime::DateFormatter * mDateFormatter; - QString mCachedLocalizedUnknownText; - - // pixmaps, never null - - QPixmap * mPixmapMessageNew; - QPixmap * mPixmapMessageUnread; - QPixmap * mPixmapMessageRead; - QPixmap * mPixmapMessageDeleted; - QPixmap * mPixmapMessageReplied; - QPixmap * mPixmapMessageRepliedAndForwarded; - QPixmap * mPixmapMessageQueued; - QPixmap * mPixmapMessageActionItem; - QPixmap * mPixmapMessageSent; - QPixmap * mPixmapMessageForwarded; - QPixmap * mPixmapMessageImportant; // "flag" - QPixmap * mPixmapMessageWatched; - QPixmap * mPixmapMessageIgnored; - QPixmap * mPixmapMessageSpam; - QPixmap * mPixmapMessageHam; - QPixmap * mPixmapMessageFullySigned; - QPixmap * mPixmapMessagePartiallySigned; - QPixmap * mPixmapMessageUndefinedSigned; - QPixmap * mPixmapMessageNotSigned; - QPixmap * mPixmapMessageFullyEncrypted; - QPixmap * mPixmapMessagePartiallyEncrypted; - QPixmap * mPixmapMessageUndefinedEncrypted; - QPixmap * mPixmapMessageNotEncrypted; - QPixmap * mPixmapMessageAttachment; - QPixmap * mPixmapMessageAnnotation; - QPixmap * mPixmapMessageInvitation; - QPixmap * mPixmapShowMore; - QPixmap * mPixmapShowLess; - QPixmap * mPixmapVerticalLine; - QPixmap * mPixmapHorizontalSpacer; + static Manager * mInstance; + QList< Widget * > mWidgetList; + QHash< QString, Aggregation * > mAggregations; + QHash< QString, Theme * > mThemes; + KMime::DateFormatter * mDateFormatter; + QString mCachedLocalizedUnknownText; + + // pixmaps, never null + + QPixmap * mPixmapMessageNew; + QPixmap * mPixmapMessageUnread; + QPixmap * mPixmapMessageRead; + QPixmap * mPixmapMessageDeleted; + QPixmap * mPixmapMessageReplied; + QPixmap * mPixmapMessageRepliedAndForwarded; + QPixmap * mPixmapMessageQueued; + QPixmap * mPixmapMessageActionItem; + QPixmap * mPixmapMessageSent; + QPixmap * mPixmapMessageForwarded; + QPixmap * mPixmapMessageImportant; // "flag" + QPixmap * mPixmapMessageWatched; + QPixmap * mPixmapMessageIgnored; + QPixmap * mPixmapMessageSpam; + QPixmap * mPixmapMessageHam; + QPixmap * mPixmapMessageFullySigned; + QPixmap * mPixmapMessagePartiallySigned; + QPixmap * mPixmapMessageUndefinedSigned; + QPixmap * mPixmapMessageNotSigned; + QPixmap * mPixmapMessageFullyEncrypted; + QPixmap * mPixmapMessagePartiallyEncrypted; + QPixmap * mPixmapMessageUndefinedEncrypted; + QPixmap * mPixmapMessageNotEncrypted; + QPixmap * mPixmapMessageAttachment; + QPixmap * mPixmapMessageAnnotation; + QPixmap * mPixmapMessageInvitation; + QPixmap * mPixmapShowMore; + QPixmap * mPixmapShowLess; + QPixmap * mPixmapVerticalLine; + QPixmap * mPixmapHorizontalSpacer; public: - // instance management - static Manager * instance() + // instance management + static Manager * instance() { return mInstance; } - // widget registration - static void registerWidget( Widget *pWidget ); - static void unregisterWidget( Widget *pWidget ); + // widget registration + static void registerWidget( Widget *pWidget ); + static void unregisterWidget( Widget *pWidget ); - const KMime::DateFormatter * dateFormatter() const + const KMime::DateFormatter * dateFormatter() const { return mDateFormatter; } - // global pixmaps - const QPixmap * pixmapMessageNew() const + // global pixmaps + const QPixmap * pixmapMessageNew() const { return mPixmapMessageNew; } - const QPixmap * pixmapMessageUnread() const + const QPixmap * pixmapMessageUnread() const { return mPixmapMessageUnread; } - const QPixmap * pixmapMessageRead() const + const QPixmap * pixmapMessageRead() const { return mPixmapMessageRead; } - const QPixmap * pixmapMessageDeleted() const + const QPixmap * pixmapMessageDeleted() const { return mPixmapMessageDeleted; } - const QPixmap * pixmapMessageReplied() const + const QPixmap * pixmapMessageReplied() const { return mPixmapMessageReplied; } - const QPixmap * pixmapMessageRepliedAndForwarded() const + const QPixmap * pixmapMessageRepliedAndForwarded() const { return mPixmapMessageRepliedAndForwarded; } - const QPixmap * pixmapMessageQueued() const + const QPixmap * pixmapMessageQueued() const { return mPixmapMessageQueued; } - const QPixmap * pixmapMessageActionItem() const + const QPixmap * pixmapMessageActionItem() const { return mPixmapMessageActionItem; } - const QPixmap * pixmapMessageSent() const + const QPixmap * pixmapMessageSent() const { return mPixmapMessageSent; } - const QPixmap * pixmapMessageForwarded() const + const QPixmap * pixmapMessageForwarded() const { return mPixmapMessageForwarded; } - const QPixmap * pixmapMessageImportant() const + const QPixmap * pixmapMessageImportant() const { return mPixmapMessageImportant; } - const QPixmap * pixmapMessageWatched() const + const QPixmap * pixmapMessageWatched() const { return mPixmapMessageWatched; } - const QPixmap * pixmapMessageIgnored() const + const QPixmap * pixmapMessageIgnored() const { return mPixmapMessageIgnored; } - const QPixmap * pixmapMessageSpam() const + const QPixmap * pixmapMessageSpam() const { return mPixmapMessageSpam; } - const QPixmap * pixmapMessageHam() const + const QPixmap * pixmapMessageHam() const { return mPixmapMessageHam; } - const QPixmap * pixmapMessageFullySigned() const + const QPixmap * pixmapMessageFullySigned() const { return mPixmapMessageFullySigned; } - const QPixmap * pixmapMessagePartiallySigned() const + const QPixmap * pixmapMessagePartiallySigned() const { return mPixmapMessagePartiallySigned; } - const QPixmap * pixmapMessageUndefinedSigned() const + const QPixmap * pixmapMessageUndefinedSigned() const { return mPixmapMessageUndefinedSigned; } - const QPixmap * pixmapMessageNotSigned() const + const QPixmap * pixmapMessageNotSigned() const { return mPixmapMessageNotSigned; } - const QPixmap * pixmapMessageFullyEncrypted() const + const QPixmap * pixmapMessageFullyEncrypted() const { return mPixmapMessageFullyEncrypted; } - const QPixmap * pixmapMessagePartiallyEncrypted() const + const QPixmap * pixmapMessagePartiallyEncrypted() const { return mPixmapMessagePartiallyEncrypted; } - const QPixmap * pixmapMessageUndefinedEncrypted() const + const QPixmap * pixmapMessageUndefinedEncrypted() const { return mPixmapMessageUndefinedEncrypted; } - const QPixmap * pixmapMessageNotEncrypted() const + const QPixmap * pixmapMessageNotEncrypted() const { return mPixmapMessageNotEncrypted; } - const QPixmap * pixmapMessageAttachment() const + const QPixmap * pixmapMessageAttachment() const { return mPixmapMessageAttachment; } - const QPixmap * pixmapMessageAnnotation() const + const QPixmap * pixmapMessageAnnotation() const { return mPixmapMessageAnnotation; } - const QPixmap * pixmapMessageInvitation() const + const QPixmap * pixmapMessageInvitation() const { return mPixmapMessageInvitation; } - const QPixmap * pixmapShowMore() const + const QPixmap * pixmapShowMore() const { return mPixmapShowMore; } - const QPixmap * pixmapShowLess() const + const QPixmap * pixmapShowLess() const { return mPixmapShowLess; } - const QPixmap * pixmapVerticalLine() const + const QPixmap * pixmapVerticalLine() const { return mPixmapVerticalLine; } - const QPixmap * pixmapHorizontalSpacer() const + const QPixmap * pixmapHorizontalSpacer() const { return mPixmapHorizontalSpacer; } - const QString & cachedLocalizedUnknownText() const + const QString & cachedLocalizedUnknownText() const { return mCachedLocalizedUnknownText; } - // aggregation sets management - const Aggregation * aggregationForStorageModel( const StorageModel *storageModel, bool *storageUsesPrivateAggregation ); - const Aggregation * aggregationForStorageModel( const QString &storageModel, bool *storageUsesPrivateAggregation ); - const Aggregation * aggregationForStorageModel( const Akonadi::Collection &storageModel, bool *storageUsesPrivateAggregation ); + // aggregation sets management + const Aggregation * aggregationForStorageModel( const StorageModel *storageModel, bool *storageUsesPrivateAggregation ); + const Aggregation * aggregationForStorageModel( const QString &storageModel, bool *storageUsesPrivateAggregation ); + const Aggregation * aggregationForStorageModel( const Akonadi::Collection &storageModel, bool *storageUsesPrivateAggregation ); - void saveAggregationForStorageModel( const StorageModel *storageModel, const QString &id, bool storageUsesPrivateAggregation ); - void saveAggregationForStorageModel( const QString &index, const QString &id, bool storageUsesPrivateAggregation ); - void saveAggregationForStorageModel( const Akonadi::Collection &col, const QString &id, bool storageUsesPrivateAggregation ); + void saveAggregationForStorageModel( const StorageModel *storageModel, const QString &id, bool storageUsesPrivateAggregation ); + void saveAggregationForStorageModel( const QString &index, const QString &id, bool storageUsesPrivateAggregation ); + void saveAggregationForStorageModel( const Akonadi::Collection &col, const QString &id, bool storageUsesPrivateAggregation ); - const Aggregation * defaultAggregation(); - const Aggregation * aggregation( const QString &id ); + const Aggregation * defaultAggregation(); + const Aggregation * aggregation( const QString &id ); - void addAggregation( Aggregation *set ); - void removeAllAggregations(); + void addAggregation( Aggregation *set ); + void removeAllAggregations(); - const QHash< QString, Aggregation * > & aggregations() const + const QHash< QString, Aggregation * > & aggregations() const { return mAggregations; } - /** + /** * This is called by the aggregation configuration dialog * once the sets have been changed. */ - void aggregationsConfigurationCompleted(); + void aggregationsConfigurationCompleted(); - // sort order management - const SortOrder sortOrderForStorageModel( const StorageModel *storageModel, bool *storageUsesPrivateSortOrder ); - void saveSortOrderForStorageModel( const StorageModel *storageModel, - const SortOrder& order, bool storageUsesPrivateSortOrder ); + // sort order management + const SortOrder sortOrderForStorageModel( const StorageModel *storageModel, bool *storageUsesPrivateSortOrder ); + void saveSortOrderForStorageModel( const StorageModel *storageModel, + const SortOrder& order, bool storageUsesPrivateSortOrder ); - // theme sets management - const Theme * themeForStorageModel( const Akonadi::Collection & col, bool * storageUsesPrivateTheme ); - const Theme * themeForStorageModel( const StorageModel *storageModel, bool *storageUsesPrivateTheme ); - const Theme * themeForStorageModel( const QString &id, bool * storageUsesPrivateTheme ); + // theme sets management + const Theme * themeForStorageModel( const Akonadi::Collection & col, bool * storageUsesPrivateTheme ); + const Theme * themeForStorageModel( const StorageModel *storageModel, bool *storageUsesPrivateTheme ); + const Theme * themeForStorageModel( const QString &id, bool * storageUsesPrivateTheme ); - void saveThemeForStorageModel( const StorageModel *storageModel, const QString &id, bool storageUsesPrivateTheme ); - void saveThemeForStorageModel( int index, const QString &id, bool storageUsesPrivateTheme ); - void saveThemeForStorageModel( const QString &storageModelIndex, const QString &id, bool storageUsesPrivateTheme ); + void saveThemeForStorageModel( const StorageModel *storageModel, const QString &id, bool storageUsesPrivateTheme ); + void saveThemeForStorageModel( int index, const QString &id, bool storageUsesPrivateTheme ); + void saveThemeForStorageModel( const QString &storageModelIndex, const QString &id, bool storageUsesPrivateTheme ); - const Theme * defaultTheme(); - const Theme * theme( const QString &id ); + const Theme * defaultTheme(); + const Theme * theme( const QString &id ); - void addTheme( Theme *set ); - void removeAllThemes(); + void addTheme( Theme *set ); + void removeAllThemes(); - const QHash< QString, Theme * > & themes() const + const QHash< QString, Theme * > & themes() const { return mThemes; } - /** + /** * This is called by the theme configuration dialog * once the sets have been changed. */ - void themesConfigurationCompleted(); + void themesConfigurationCompleted(); protected slots: - /** + /** * Reloads the global configuration from the config files (so we assume it has changed) * The settings private to MessageList (like Themes or Aggregations) aren't reloaded. * If the global configuration has changed then all the views are reloaded. */ - void reloadGlobalConfiguration(); + void reloadGlobalConfiguration(); - /** + /** * Explicitly reloads the contents of all the widgets. */ - void reloadAllWidgets(); + void reloadAllWidgets(); signals: - void aggregationsChanged(); - void themesChanged(); + void aggregationsChanged(); + void themesChanged(); private: - // internal configuration stuff - void loadConfiguration(); - void saveConfiguration(); - void loadGlobalConfiguration(); - void saveGlobalConfiguration(); - - // internal option set management - void createDefaultAggregations(); - void createDefaultThemes(); + // internal configuration stuff + void loadConfiguration(); + void saveConfiguration(); + void loadGlobalConfiguration(); + void saveGlobalConfiguration(); + + // internal option set management + void createDefaultAggregations(); + void createDefaultThemes(); }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/messageitem.cpp kdepim-4.13.0/messagelist/core/messageitem.cpp --- kdepim-4.12.97/messagelist/core/messageitem.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/messageitem.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -39,87 +39,87 @@ class MessageItem::Tag::Private { -public: - Private() - :mPriority( 0 ) //Initialize it + public: + Private() + :mPriority( 0 ) //Initialize it { } - QPixmap mPixmap; - QString mName; - QString mId; ///< The unique id of this tag - QColor mTextColor; - QColor mBackgroundColor; - QFont mFont; - int mPriority; + QPixmap mPixmap; + QString mName; + QString mId; ///< The unique id of this tag + QColor mTextColor; + QColor mBackgroundColor; + QFont mFont; + int mPriority; }; MessageItem::Tag::Tag( const QPixmap &pix, const QString &tagName, const QString &tagId ) - : d( new Private ) + : d( new Private ) { - d->mPixmap = pix; - d->mName = tagName; - d->mId = tagId; + d->mPixmap = pix; + d->mName = tagName; + d->mId = tagId; } MessageItem::Tag::~Tag() { - delete d; + delete d; } QPixmap MessageItem::Tag::pixmap() const { - return d->mPixmap; + return d->mPixmap; } QString MessageItem::Tag::name() const { - return d->mName; + return d->mName; } QString MessageItem::Tag::id() const { - return d->mId; + return d->mId; } QColor MessageItem::Tag::textColor() const { - return d->mTextColor; + return d->mTextColor; } QColor MessageItem::Tag::backgroundColor() const { - return d->mBackgroundColor; + return d->mBackgroundColor; } QFont MessageItem::Tag::font() const { - return d->mFont; + return d->mFont; } int MessageItem::Tag::priority() const { - return d->mPriority; + return d->mPriority; } void MessageItem::Tag::setTextColor( const QColor &textColor ) { - d->mTextColor = textColor; + d->mTextColor = textColor; } void MessageItem::Tag::setBackgroundColor( const QColor &backgroundColor ) { - d->mBackgroundColor = backgroundColor; + d->mBackgroundColor = backgroundColor; } void MessageItem::Tag::setFont( const QFont &font ) { - d->mFont = font; + d->mFont = font; } void MessageItem::Tag::setPriority( int priority ) { - d->mPriority = priority; + d->mPriority = priority; } @@ -142,29 +142,29 @@ K_GLOBAL_STATIC(MessageItemPrivateSettings, s_settings) MessageItemPrivate::MessageItemPrivate( MessageItem* qq ) - : ItemPrivate( qq ), - mThreadingStatus( MessageItem::ParentMissing ), - mEncryptionState( MessageItem::NotEncrypted ), - mSignatureState( MessageItem::NotSigned ), - mAboutToBeRemoved( false ), - mSubjectIsPrefixed( false ), - mTagList( 0 ) + : ItemPrivate( qq ), + mThreadingStatus( MessageItem::ParentMissing ), + mEncryptionState( MessageItem::NotEncrypted ), + mSignatureState( MessageItem::NotSigned ), + mAboutToBeRemoved( false ), + mSubjectIsPrefixed( false ), + mTagList( 0 ) { } MessageItemPrivate::~MessageItemPrivate() { - s_tagCache->cancelRequest(this); - invalidateTagCache(); + s_tagCache->cancelRequest(this); + invalidateTagCache(); } void MessageItemPrivate::invalidateTagCache() { - if ( mTagList ) { - qDeleteAll( *mTagList ); - delete mTagList; - mTagList = 0; - } + if ( mTagList ) { + qDeleteAll( *mTagList ); + delete mTagList; + mTagList = 0; + } } void MessageItemPrivate::invalidateAnnotationCache() @@ -173,77 +173,77 @@ const MessageItem::Tag* MessageItemPrivate::bestTag() const { - const MessageItem::Tag *best = 0; - foreach( const MessageItem::Tag* tag, getTagList() ) { - if ( !best || tag->priority() < best->priority() ) - best = tag; - } - return best; + const MessageItem::Tag *best = 0; + foreach( const MessageItem::Tag* tag, getTagList() ) { + if ( !best || tag->priority() < best->priority() ) + best = tag; + } + return best; } void MessageItemPrivate::fillTagList(const Akonadi::Tag::List &taglist) { - Q_ASSERT( !mTagList ); - mTagList = new QList; + Q_ASSERT( !mTagList ); + mTagList = new QList; - // TODO: The tag pointers here could be shared between all items, there really is no point in - // creating them for each item that has tags + // TODO: The tag pointers here could be shared between all items, there really is no point in + // creating them for each item that has tags - //Priority sort this and make bestTag more efficient + //Priority sort this and make bestTag more efficient - foreach( const Akonadi::Tag &tag, taglist ) { - QString symbol = QLatin1String( "mail-tagged" ); - Akonadi::TagAttribute *attr = tag.attribute(); - if (attr) { - if (!attr->iconName().isEmpty()) { - symbol = attr->iconName(); - } - } - MessageItem::Tag *messageListTag = - new MessageItem::Tag( SmallIcon( symbol ), tag.name(), tag.url().url() ); - - if (attr) { - messageListTag->setTextColor( attr->textColor() ); - messageListTag->setBackgroundColor( attr->backgroundColor() ); - if (!attr->font().isEmpty()) { - QFont font; - if (font.fromString( attr->font() )) { - messageListTag->setFont( font ); + foreach( const Akonadi::Tag &tag, taglist ) { + QString symbol = QLatin1String( "mail-tagged" ); + Akonadi::TagAttribute *attr = tag.attribute(); + if (attr) { + if (!attr->iconName().isEmpty()) { + symbol = attr->iconName(); + } + } + MessageItem::Tag *messageListTag = + new MessageItem::Tag( SmallIcon( symbol ), tag.name(), tag.url().url() ); + + if (attr) { + messageListTag->setTextColor( attr->textColor() ); + messageListTag->setBackgroundColor( attr->backgroundColor() ); + if (!attr->font().isEmpty()) { + QFont font; + if (font.fromString( attr->font() )) { + messageListTag->setFont( font ); + } + } + if (attr->priority() != -1) { + messageListTag->setPriority( attr->priority() ); + } else { + messageListTag->setPriority( 0xFFFF ); + } } - } - if (attr->priority() != -1) { - messageListTag->setPriority( attr->priority() ); - } else { - messageListTag->setPriority( 0xFFFF ); - } - } - mTagList->append( messageListTag ); - } + mTagList->append( messageListTag ); + } } QList MessageItemPrivate::getTagList() const { - if ( !mTagList ) { - s_tagCache->retrieveTags(mAkonadiItem.tags(), const_cast(this)); - return QList(); - } + if ( !mTagList ) { + s_tagCache->retrieveTags(mAkonadiItem.tags(), const_cast(this)); + return QList(); + } - return *mTagList; + return *mTagList; } bool MessageItemPrivate::tagListInitialized() const { - return mTagList != 0; + return mTagList != 0; } MessageItem::MessageItem() - : Item( Message, new MessageItemPrivate( this ) ), ModelInvariantIndex() + : Item( Message, new MessageItemPrivate( this ) ), ModelInvariantIndex() { } MessageItem::MessageItem ( MessageItemPrivate* dd ) - : Item ( Message, dd ), ModelInvariantIndex() + : Item ( Message, dd ), ModelInvariantIndex() { } @@ -253,413 +253,413 @@ QList< MessageItem::Tag * > MessageItem::tagList() const { - Q_D( const MessageItem ); - return d->getTagList(); + Q_D( const MessageItem ); + return d->getTagList(); } bool MessageItem::hasAnnotation() const { - Q_D( const MessageItem ); - //TODO check for note entry? - return d->mAkonadiItem.hasAttribute(); + Q_D( const MessageItem ); + //TODO check for note entry? + return d->mAkonadiItem.hasAttribute(); } QString MessageItem::annotation() const { - Q_D( const MessageItem ); - if ( d->mAkonadiItem.hasAttribute() ) { - Akonadi::EntityAnnotationsAttribute *attr = d->mAkonadiItem.attribute(); - const QMap annotations = attr->annotations(); - if (annotations.contains("/private/comment")) { - return QString::fromLatin1(annotations.value("/private/comment")); - } - if (annotations.contains("/shared/comment")) { - return QString::fromLatin1(annotations.value("/shared/comment")); + Q_D( const MessageItem ); + if ( d->mAkonadiItem.hasAttribute() ) { + Akonadi::EntityAnnotationsAttribute *attr = d->mAkonadiItem.attribute(); + const QMap annotations = attr->annotations(); + if (annotations.contains("/private/comment")) { + return QString::fromLatin1(annotations.value("/private/comment")); + } + if (annotations.contains("/shared/comment")) { + return QString::fromLatin1(annotations.value("/shared/comment")); + } } - } - return QString(); + return QString(); } void MessageItem::editAnnotation() { - Q_D( MessageItem ); - if ( d->mAnnotationDialog.data() ) - return; - d->mAnnotationDialog = new MessageCore::AnnotationEditDialog( d->mAkonadiItem ); - d->mAnnotationDialog.data()->setAttribute( Qt::WA_DeleteOnClose ); - //FIXME make async - if ( d->mAnnotationDialog.data()->exec() ) { - // invalidate the cached mHasAnnotation value - } + Q_D( MessageItem ); + if ( d->mAnnotationDialog.data() ) + return; + d->mAnnotationDialog = new MessageCore::AnnotationEditDialog( d->mAkonadiItem ); + d->mAnnotationDialog.data()->setAttribute( Qt::WA_DeleteOnClose ); + //FIXME make async + if ( d->mAnnotationDialog.data()->exec() ) { + // invalidate the cached mHasAnnotation value + } } const MessageItem::Tag * MessageItemPrivate::findTagInternal( const QString &szTagId ) const { - foreach( const MessageItem::Tag *tag, getTagList() ) { - if ( tag->id() == szTagId ) - return tag; - } - return 0; + foreach( const MessageItem::Tag *tag, getTagList() ) { + if ( tag->id() == szTagId ) + return tag; + } + return 0; } const MessageItem::Tag *MessageItem::findTag( const QString &szTagId ) const { - Q_D( const MessageItem ); - return d->findTagInternal( szTagId ); + Q_D( const MessageItem ); + return d->findTagInternal( szTagId ); } QString MessageItem::tagListDescription() const { - QString ret; + QString ret; - foreach( const Tag *tag, tagList() ) { - if ( !ret.isEmpty() ) - ret += QLatin1String( ", " ); - ret += tag->name(); - } + foreach( const Tag *tag, tagList() ) { + if ( !ret.isEmpty() ) + ret += QLatin1String( ", " ); + ret += tag->name(); + } - return ret; + return ret; } void MessageItem::invalidateTagCache() { - Q_D( MessageItem ); - d->invalidateTagCache(); + Q_D( MessageItem ); + d->invalidateTagCache(); } void MessageItem::invalidateAnnotationCache() { - Q_D( MessageItem ); - d->invalidateAnnotationCache(); + Q_D( MessageItem ); + d->invalidateAnnotationCache(); } QColor MessageItem::textColor() const { - Q_D( const MessageItem ); - const Tag *bestTag = d->bestTag(); - if ( bestTag != 0 && bestTag->textColor().isValid() ) { - return bestTag->textColor(); - } - QColor clr; - Akonadi::MessageStatus messageStatus = status(); - if ( !messageStatus.isRead() ) { - clr = s_settings->mColorUnreadMessage; - } else if ( messageStatus.isImportant() ) { - clr = s_settings->mColorImportantMessage; - } else if ( messageStatus.isToAct() ) { - clr = s_settings->mColorToDoMessage; - } + Q_D( const MessageItem ); + const Tag *bestTag = d->bestTag(); + if ( bestTag != 0 && bestTag->textColor().isValid() ) { + return bestTag->textColor(); + } + QColor clr; + Akonadi::MessageStatus messageStatus = status(); + if ( !messageStatus.isRead() ) { + clr = s_settings->mColorUnreadMessage; + } else if ( messageStatus.isImportant() ) { + clr = s_settings->mColorImportantMessage; + } else if ( messageStatus.isToAct() ) { + clr = s_settings->mColorToDoMessage; + } - return clr; + return clr; } QColor MessageItem::backgroundColor() const { - Q_D( const MessageItem ); - const Tag *bestTag = d->bestTag(); - if ( bestTag ) { - return bestTag->backgroundColor(); - } else { - return QColor(); - } + Q_D( const MessageItem ); + const Tag *bestTag = d->bestTag(); + if ( bestTag ) { + return bestTag->backgroundColor(); + } else { + return QColor(); + } } QFont MessageItem::font() const { - Q_D( const MessageItem ); - // for performance reasons we don't want font retrieval to trigger - // full tags loading, as the font is used for geometry calculation - // and thus this method called for each item - if ( d->tagListInitialized() ) { - const Tag *bestTag = d->bestTag(); - if ( bestTag && bestTag->font() != QFont() ) { - return bestTag->font(); + Q_D( const MessageItem ); + // for performance reasons we don't want font retrieval to trigger + // full tags loading, as the font is used for geometry calculation + // and thus this method called for each item + if ( d->tagListInitialized() ) { + const Tag *bestTag = d->bestTag(); + if ( bestTag && bestTag->font() != QFont() ) { + return bestTag->font(); + } } - } - QFont font; + QFont font; - // from KDE3: "important" overrides "new" overrides "unread" overrides "todo" - Akonadi::MessageStatus messageStatus = status(); - if ( messageStatus.isImportant() ) { - font = s_settings->mFontImportantMessage; - } else if ( !messageStatus.isRead() ) { - font = s_settings->mFontUnreadMessage; - } else if ( messageStatus.isToAct() ) { - font = s_settings->mFontToDoMessage; - } else { - font = s_settings->mFont; - } + // from KDE3: "important" overrides "new" overrides "unread" overrides "todo" + Akonadi::MessageStatus messageStatus = status(); + if ( messageStatus.isImportant() ) { + font = s_settings->mFontImportantMessage; + } else if ( !messageStatus.isRead() ) { + font = s_settings->mFontUnreadMessage; + } else if ( messageStatus.isToAct() ) { + font = s_settings->mFontToDoMessage; + } else { + font = s_settings->mFont; + } - return font; + return font; } QString MessageItem::fontKey() const { - Q_D( const MessageItem ); + Q_D( const MessageItem ); - // for performance reasons we don't want font retrieval to trigger - // full tags loading, as the font is used for geometry calculation - // and thus this method called for each item - if ( d->tagListInitialized() ) { - const Tag *bestTag = d->bestTag(); - if ( bestTag && bestTag->font() != QFont() ) { - return bestTag->font().key(); + // for performance reasons we don't want font retrieval to trigger + // full tags loading, as the font is used for geometry calculation + // and thus this method called for each item + if ( d->tagListInitialized() ) { + const Tag *bestTag = d->bestTag(); + if ( bestTag && bestTag->font() != QFont() ) { + return bestTag->font().key(); + } } - } - // from KDE3: "important" overrides "new" overrides "unread" overrides "todo" - Akonadi::MessageStatus messageStatus = status(); - if ( messageStatus.isImportant() ) { - return s_settings->mFontImportantMessageKey; - } else if ( !messageStatus.isRead() ) { - return s_settings->mFontUnreadMessageKey; - } else if ( messageStatus.isToAct() ) { - return s_settings->mFontToDoMessageKey; - } else { - return s_settings->mFontKey; - } + // from KDE3: "important" overrides "new" overrides "unread" overrides "todo" + Akonadi::MessageStatus messageStatus = status(); + if ( messageStatus.isImportant() ) { + return s_settings->mFontImportantMessageKey; + } else if ( !messageStatus.isRead() ) { + return s_settings->mFontUnreadMessageKey; + } else if ( messageStatus.isToAct() ) { + return s_settings->mFontToDoMessageKey; + } else { + return s_settings->mFontKey; + } } MessageItem::SignatureState MessageItem::signatureState() const { - Q_D( const MessageItem ); - return d->mSignatureState; + Q_D( const MessageItem ); + return d->mSignatureState; } void MessageItem::setSignatureState( SignatureState state ) { - Q_D( MessageItem ); - d->mSignatureState = state; + Q_D( MessageItem ); + d->mSignatureState = state; } MessageItem::EncryptionState MessageItem::encryptionState() const { - Q_D( const MessageItem ); - return d->mEncryptionState; + Q_D( const MessageItem ); + return d->mEncryptionState; } void MessageItem::setEncryptionState( EncryptionState state ) { - Q_D( MessageItem ); - d->mEncryptionState = state; + Q_D( MessageItem ); + d->mEncryptionState = state; } QByteArray MessageItem::messageIdMD5() const { - Q_D( const MessageItem ); - return d->mMessageIdMD5; + Q_D( const MessageItem ); + return d->mMessageIdMD5; } void MessageItem::setMessageIdMD5( const QByteArray &md5 ) { - Q_D( MessageItem ); - d->mMessageIdMD5 = md5; + Q_D( MessageItem ); + d->mMessageIdMD5 = md5; } QByteArray MessageItem::inReplyToIdMD5() const { - Q_D( const MessageItem ); - return d->mInReplyToIdMD5; + Q_D( const MessageItem ); + return d->mInReplyToIdMD5; } void MessageItem::setInReplyToIdMD5( const QByteArray& md5 ) { - Q_D( MessageItem ); - d->mInReplyToIdMD5 = md5; + Q_D( MessageItem ); + d->mInReplyToIdMD5 = md5; } QByteArray MessageItem::referencesIdMD5() const { - Q_D( const MessageItem ); - return d->mReferencesIdMD5; + Q_D( const MessageItem ); + return d->mReferencesIdMD5; } void MessageItem::setReferencesIdMD5( const QByteArray& md5 ) { - Q_D( MessageItem ); - d->mReferencesIdMD5 = md5; + Q_D( MessageItem ); + d->mReferencesIdMD5 = md5; } void MessageItem::setSubjectIsPrefixed( bool subjectIsPrefixed ) { - Q_D( MessageItem ); - d->mSubjectIsPrefixed = subjectIsPrefixed; + Q_D( MessageItem ); + d->mSubjectIsPrefixed = subjectIsPrefixed; } bool MessageItem::subjectIsPrefixed() const { - Q_D( const MessageItem ); - return d->mSubjectIsPrefixed; + Q_D( const MessageItem ); + return d->mSubjectIsPrefixed; } QByteArray MessageItem::strippedSubjectMD5() const { - Q_D( const MessageItem ); - return d->mStrippedSubjectMD5; + Q_D( const MessageItem ); + return d->mStrippedSubjectMD5; } void MessageItem::setStrippedSubjectMD5( const QByteArray& md5 ) { - Q_D( MessageItem ); - d->mStrippedSubjectMD5 = md5; + Q_D( MessageItem ); + d->mStrippedSubjectMD5 = md5; } bool MessageItem::aboutToBeRemoved() const { - Q_D( const MessageItem ); - return d->mAboutToBeRemoved; + Q_D( const MessageItem ); + return d->mAboutToBeRemoved; } void MessageItem::setAboutToBeRemoved( bool aboutToBeRemoved ) { - Q_D( MessageItem ); - d->mAboutToBeRemoved = aboutToBeRemoved; + Q_D( MessageItem ); + d->mAboutToBeRemoved = aboutToBeRemoved; } MessageItem::ThreadingStatus MessageItem::threadingStatus() const { - Q_D( const MessageItem ); - return d->mThreadingStatus; + Q_D( const MessageItem ); + return d->mThreadingStatus; } void MessageItem::setThreadingStatus( ThreadingStatus threadingStatus ) { - Q_D( MessageItem ); - d->mThreadingStatus = threadingStatus; + Q_D( MessageItem ); + d->mThreadingStatus = threadingStatus; } unsigned long MessageItem::uniqueId() const { - Q_D( const MessageItem ); - return d->mAkonadiItem.id(); + Q_D( const MessageItem ); + return d->mAkonadiItem.id(); } Akonadi::Item MessageList::Core::MessageItem::akonadiItem() const { - Q_D( const MessageItem ); - return d->mAkonadiItem; + Q_D( const MessageItem ); + return d->mAkonadiItem; } void MessageList::Core::MessageItem::setAkonadiItem(const Akonadi::Item& item) { - Q_D( MessageItem ); - d->mAkonadiItem = item; + Q_D( MessageItem ); + d->mAkonadiItem = item; } MessageItem * MessageItem::topmostMessage() { - if ( !parent() ) + if ( !parent() ) + return this; + if ( parent()->type() == Item::Message ) + return static_cast< MessageItem * >( parent() )->topmostMessage(); return this; - if ( parent()->type() == Item::Message ) - return static_cast< MessageItem * >( parent() )->topmostMessage(); - return this; } QString MessageItem::accessibleTextForField(Theme::ContentItem::Type field) { - switch (field) { - case Theme::ContentItem::Subject: - return d_ptr->mSubject; - case Theme::ContentItem::Sender: - return d_ptr->mSender; - case Theme::ContentItem::Receiver: - return d_ptr->mReceiver; - case Theme::ContentItem::SenderOrReceiver: - return senderOrReceiver(); - case Theme::ContentItem::Date: - return formattedDate(); - case Theme::ContentItem::Size: - return formattedSize(); - case Theme::ContentItem::RepliedStateIcon: - return status().isReplied() ? i18nc( "Status of an item", "Replied" ) : QString(); - case Theme::ContentItem::ReadStateIcon: - return status().isRead() ? i18nc( "Status of an item", "Read" ) : i18nc( "Status of an item", "Unread" ); - case Theme::ContentItem::CombinedReadRepliedStateIcon: - return accessibleTextForField( Theme::ContentItem::ReadStateIcon ) + accessibleTextForField( Theme::ContentItem::RepliedStateIcon ); - default: - return QString(); - } + switch (field) { + case Theme::ContentItem::Subject: + return d_ptr->mSubject; + case Theme::ContentItem::Sender: + return d_ptr->mSender; + case Theme::ContentItem::Receiver: + return d_ptr->mReceiver; + case Theme::ContentItem::SenderOrReceiver: + return senderOrReceiver(); + case Theme::ContentItem::Date: + return formattedDate(); + case Theme::ContentItem::Size: + return formattedSize(); + case Theme::ContentItem::RepliedStateIcon: + return status().isReplied() ? i18nc( "Status of an item", "Replied" ) : QString(); + case Theme::ContentItem::ReadStateIcon: + return status().isRead() ? i18nc( "Status of an item", "Read" ) : i18nc( "Status of an item", "Unread" ); + case Theme::ContentItem::CombinedReadRepliedStateIcon: + return accessibleTextForField( Theme::ContentItem::ReadStateIcon ) + accessibleTextForField( Theme::ContentItem::RepliedStateIcon ); + default: + return QString(); + } } QString MessageItem::accessibleText( const Theme* theme, int columnIndex ) { - QStringList rowsTexts; + QStringList rowsTexts; - Q_FOREACH( Theme::Row *row, theme->column(columnIndex)->messageRows() ) { - QStringList leftStrings; - QStringList rightStrings; - Q_FOREACH( Theme::ContentItem *contentItem, row->leftItems() ) { - leftStrings.append( accessibleTextForField( contentItem->type() ) ); - } + Q_FOREACH( Theme::Row *row, theme->column(columnIndex)->messageRows() ) { + QStringList leftStrings; + QStringList rightStrings; + Q_FOREACH( Theme::ContentItem *contentItem, row->leftItems() ) { + leftStrings.append( accessibleTextForField( contentItem->type() ) ); + } - Q_FOREACH( Theme::ContentItem *contentItem, row->rightItems() ) { - rightStrings.insert( rightStrings.begin(), accessibleTextForField( contentItem->type() ) ); - } + Q_FOREACH( Theme::ContentItem *contentItem, row->rightItems() ) { + rightStrings.insert( rightStrings.begin(), accessibleTextForField( contentItem->type() ) ); + } - rowsTexts.append( ( leftStrings + rightStrings ).join( QLatin1String( " " ) ) ); - } + rowsTexts.append( ( leftStrings + rightStrings ).join( QLatin1String( " " ) ) ); + } - return rowsTexts.join( QLatin1String(" ") ); + return rowsTexts.join( QLatin1String(" ") ); } void MessageItem::subTreeToList( QList< MessageItem * > &list ) { - list.append( this ); - QList< Item * > * childList = childItems(); - if ( !childList ) - return; - QList< Item * >::ConstIterator end( childList->constEnd() ); - for ( QList< Item * >::ConstIterator it = childList->constBegin(); it != end; ++it ) - { - Q_ASSERT( ( *it )->type() == Item::Message ); - static_cast< MessageItem * >( *it )->subTreeToList( list ); - } + list.append( this ); + QList< Item * > * childList = childItems(); + if ( !childList ) + return; + QList< Item * >::ConstIterator end( childList->constEnd() ); + for ( QList< Item * >::ConstIterator it = childList->constBegin(); it != end; ++it ) + { + Q_ASSERT( ( *it )->type() == Item::Message ); + static_cast< MessageItem * >( *it )->subTreeToList( list ); + } } void MessageItem::setUnreadMessageColor( const QColor &color ) { - s_settings->mColorUnreadMessage = color; + s_settings->mColorUnreadMessage = color; } void MessageItem::setImportantMessageColor( const QColor &color ) { - s_settings->mColorImportantMessage = color; + s_settings->mColorImportantMessage = color; } void MessageItem::setToDoMessageColor( const QColor &color ) { - s_settings->mColorToDoMessage = color; + s_settings->mColorToDoMessage = color; } void MessageItem::setGeneralFont( const QFont &font ) { - s_settings->mFont = font; - s_settings->mFontKey = font.key(); + s_settings->mFont = font; + s_settings->mFontKey = font.key(); } void MessageItem::setUnreadMessageFont( const QFont &font ) { - s_settings->mFontUnreadMessage = font; - s_settings->mFontUnreadMessageKey = font.key(); + s_settings->mFontUnreadMessage = font; + s_settings->mFontUnreadMessageKey = font.key(); } void MessageItem::setImportantMessageFont( const QFont &font ) { - s_settings->mFontImportantMessage = font; - s_settings->mFontImportantMessageKey = font.key(); + s_settings->mFontImportantMessage = font; + s_settings->mFontImportantMessageKey = font.key(); } void MessageItem::setToDoMessageFont( const QFont &font ) { - s_settings->mFontToDoMessage = font; - s_settings->mFontToDoMessageKey = font.key(); + s_settings->mFontToDoMessage = font; + s_settings->mFontToDoMessageKey = font.key(); } FakeItemPrivate::FakeItemPrivate( FakeItem *qq ) : MessageItemPrivate( qq ) @@ -667,7 +667,7 @@ } FakeItem::FakeItem() - : MessageItem( new FakeItemPrivate( this ) ) + : MessageItem( new FakeItemPrivate( this ) ) { } @@ -677,94 +677,94 @@ QList< MessageItem::Tag * > FakeItem::tagList() const { - Q_D( const FakeItem ); - return d->mFakeTags; + Q_D( const FakeItem ); + return d->mFakeTags; } void FakeItem::setFakeTags( const QList< MessageItem::Tag* > &tagList ) { - Q_D( FakeItem ); - d->mFakeTags = tagList; + Q_D( FakeItem ); + d->mFakeTags = tagList; } bool FakeItem::hasAnnotation() const { - return true; + return true; } TagCache::TagCache() - :QObject(), - mMonitor(new Akonadi::Monitor(this)) + :QObject(), + mMonitor(new Akonadi::Monitor(this)) { - mCache.setMaxCost(100); - mMonitor->setTypeMonitored(Akonadi::Monitor::Tags); - mMonitor->tagFetchScope().fetchAttribute(); - connect(mMonitor, SIGNAL(tagAdded(Akonadi::Tag)), this, SLOT(onTagAdded(Akonadi::Tag))); - connect(mMonitor, SIGNAL(tagRemoved(Akonadi::Tag)), this, SLOT(onTagRemoved(Akonadi::Tag))); - connect(mMonitor, SIGNAL(tagChanged(Akonadi::Tag)), this, SLOT(onTagChanged(Akonadi::Tag))); + mCache.setMaxCost(100); + mMonitor->setTypeMonitored(Akonadi::Monitor::Tags); + mMonitor->tagFetchScope().fetchAttribute(); + connect(mMonitor, SIGNAL(tagAdded(Akonadi::Tag)), this, SLOT(onTagAdded(Akonadi::Tag))); + connect(mMonitor, SIGNAL(tagRemoved(Akonadi::Tag)), this, SLOT(onTagRemoved(Akonadi::Tag))); + connect(mMonitor, SIGNAL(tagChanged(Akonadi::Tag)), this, SLOT(onTagChanged(Akonadi::Tag))); } void TagCache::onTagAdded(const Akonadi::Tag &tag) { - mCache.insert(tag.id(), new Akonadi::Tag(tag)); + mCache.insert(tag.id(), new Akonadi::Tag(tag)); } void TagCache::onTagChanged(const Akonadi::Tag &tag) { - mCache.remove(tag.id()); + mCache.remove(tag.id()); } void TagCache::onTagRemoved(const Akonadi::Tag &tag) { - mCache.remove(tag.id()); + mCache.remove(tag.id()); } void TagCache::retrieveTags(const Akonadi::Tag::List &tags, MessageItemPrivate *m) { - //Retrieval is in progress - if (mRequests.key(m)) { - return; - } - Akonadi::Tag::List toFetch; - Akonadi::Tag::List available; - Q_FOREACH( const Akonadi::Tag &tag, tags ) { - if (mCache.contains(tag.id())) { - available << *mCache.object(tag.id()); + //Retrieval is in progress + if (mRequests.key(m)) { + return; + } + Akonadi::Tag::List toFetch; + Akonadi::Tag::List available; + Q_FOREACH( const Akonadi::Tag &tag, tags ) { + if (mCache.contains(tag.id())) { + available << *mCache.object(tag.id()); + } else { + toFetch << tag; + } + } + //Because fillTagList expects to be called once we either fetch all or none + if (!toFetch.isEmpty()) { + Akonadi::TagFetchJob *tagFetchJob = new Akonadi::TagFetchJob(tags, this); + tagFetchJob->fetchScope().fetchAttribute(); + connect(tagFetchJob, SIGNAL(result(KJob*)), this, SLOT(onTagsFetched(KJob*))); + mRequests.insert(tagFetchJob, m); } else { - toFetch << tag; + m->fillTagList(available); } - } - //Because fillTagList expects to be called once we either fetch all or none - if (!toFetch.isEmpty()) { - Akonadi::TagFetchJob *tagFetchJob = new Akonadi::TagFetchJob(tags, this); - tagFetchJob->fetchScope().fetchAttribute(); - connect(tagFetchJob, SIGNAL(result(KJob*)), this, SLOT(onTagsFetched(KJob*))); - mRequests.insert(tagFetchJob, m); - } else { - m->fillTagList(available); - } } void TagCache::cancelRequest(MessageItemPrivate *m) { - const QList keys = mRequests.keys(m); - Q_FOREACH( KJob *job, keys ) { - mRequests.remove(job); - } + const QList keys = mRequests.keys(m); + Q_FOREACH( KJob *job, keys ) { + mRequests.remove(job); + } } void TagCache::onTagsFetched(KJob *job) { - if (job->error()) { - kWarning() << "Failed to fetch tags: " << job->errorString(); - return; - } - Akonadi::TagFetchJob *fetchJob = static_cast(job); - Q_FOREACH( const Akonadi::Tag &tag, fetchJob->tags() ) { - mCache.insert(tag.id(), new Akonadi::Tag(tag)); - } - MessageItemPrivate *m = mRequests.take(fetchJob); - if (m) { - m->fillTagList(fetchJob->tags()); - } + if (job->error()) { + kWarning() << "Failed to fetch tags: " << job->errorString(); + return; + } + Akonadi::TagFetchJob *fetchJob = static_cast(job); + Q_FOREACH( const Akonadi::Tag &tag, fetchJob->tags() ) { + mCache.insert(tag.id(), new Akonadi::Tag(tag)); + } + MessageItemPrivate *m = mRequests.take(fetchJob); + if (m) { + m->fillTagList(fetchJob->tags()); + } } diff -Nru kdepim-4.12.97/messagelist/core/messageitem.h kdepim-4.13.0/messagelist/core/messageitem.h --- kdepim-4.12.97/messagelist/core/messageitem.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/messageitem.h 2014-04-10 07:40:20.000000000 +0000 @@ -46,165 +46,165 @@ class MESSAGELIST_EXPORT MessageItem : public Item, public ModelInvariantIndex { public: - class MESSAGELIST_EXPORT Tag - { - public: - explicit Tag( const QPixmap &pix, const QString &tagName, const QString &tagId ); - ~Tag(); - QPixmap pixmap() const; - QString name() const; - QString id() const; - QColor textColor() const; - QColor backgroundColor() const; - QFont font() const; - int priority() const; + class MESSAGELIST_EXPORT Tag + { + public: + explicit Tag( const QPixmap &pix, const QString &tagName, const QString &tagId ); + ~Tag(); + QPixmap pixmap() const; + QString name() const; + QString id() const; + QColor textColor() const; + QColor backgroundColor() const; + QFont font() const; + int priority() const; + + void setTextColor( const QColor &textColor ); + void setBackgroundColor( const QColor &backgroundColor ); + void setFont( const QFont &font ); + void setPriority( int priority ); + + private: + class Private; + Private * const d; + }; + + enum ThreadingStatus + { + PerfectParentFound, ///< this message found a perfect parent to attach to + ImperfectParentFound, ///< this message found an imperfect parent to attach to (might be fixed later) + ParentMissing, ///< this message might belong to a thread but its parent is actually missing + NonThreadable ///< this message does not look as being threadable + }; + + enum EncryptionState + { + NotEncrypted, + PartiallyEncrypted, + FullyEncrypted, + EncryptionStateUnknown + }; + + enum SignatureState + { + NotSigned, + PartiallySigned, + FullySigned, + SignatureStateUnknown + }; - void setTextColor( const QColor &textColor ); - void setBackgroundColor( const QColor &backgroundColor ); - void setFont( const QFont &font ); - void setPriority( int priority ); - - private: - class Private; - Private * const d; - }; - - enum ThreadingStatus - { - PerfectParentFound, ///< this message found a perfect parent to attach to - ImperfectParentFound, ///< this message found an imperfect parent to attach to (might be fixed later) - ParentMissing, ///< this message might belong to a thread but its parent is actually missing - NonThreadable ///< this message does not look as being threadable - }; - - enum EncryptionState - { - NotEncrypted, - PartiallyEncrypted, - FullyEncrypted, - EncryptionStateUnknown - }; - - enum SignatureState - { - NotSigned, - PartiallySigned, - FullySigned, - SignatureStateUnknown - }; - - explicit MessageItem(); - virtual ~MessageItem(); + explicit MessageItem(); + virtual ~MessageItem(); public: - /// Returns the list of tags for this item. - virtual QList< Tag * > tagList() const; + /// Returns the list of tags for this item. + virtual QList< Tag * > tagList() const; - /// Returns true if this message has an annotation. - virtual bool hasAnnotation() const; + /// Returns true if this message has an annotation. + virtual bool hasAnnotation() const; - /// Returns the annotation of the message, given that hasAnnotation() is true - QString annotation() const; + /// Returns the annotation of the message, given that hasAnnotation() is true + QString annotation() const; - /// Shows a dialog to edit or delete the annotation - void editAnnotation(); + /// Shows a dialog to edit or delete the annotation + void editAnnotation(); - /** + /** * Returns Tag associated to this message that has the specified id or 0 * if no such tag exists. mTagList will be 0 in 99% of the cases. */ - const Tag * findTag( const QString &szTagId ) const; + const Tag * findTag( const QString &szTagId ) const; - QString tagListDescription() const; + QString tagListDescription() const; - /// Deletes all cached tags. The next time someone asks this item for the tags, they are - /// fetched again - void invalidateTagCache(); + /// Deletes all cached tags. The next time someone asks this item for the tags, they are + /// fetched again + void invalidateTagCache(); - /// Same as invalidateTagCache(), only for the annotation - void invalidateAnnotationCache(); + /// Same as invalidateTagCache(), only for the annotation + void invalidateAnnotationCache(); - QColor textColor() const; + QColor textColor() const; - QColor backgroundColor() const; + QColor backgroundColor() const; - QFont font() const; + QFont font() const; - QString fontKey() const; + QString fontKey() const; - SignatureState signatureState() const; + SignatureState signatureState() const; - void setSignatureState( SignatureState state ); + void setSignatureState( SignatureState state ); - EncryptionState encryptionState() const; + EncryptionState encryptionState() const; - void setEncryptionState( EncryptionState state ); + void setEncryptionState( EncryptionState state ); - QByteArray messageIdMD5() const; + QByteArray messageIdMD5() const; - void setMessageIdMD5( const QByteArray &md5 ); + void setMessageIdMD5( const QByteArray &md5 ); - QByteArray inReplyToIdMD5() const; + QByteArray inReplyToIdMD5() const; - void setInReplyToIdMD5( const QByteArray &md5 ); + void setInReplyToIdMD5( const QByteArray &md5 ); - QByteArray referencesIdMD5() const; + QByteArray referencesIdMD5() const; - void setReferencesIdMD5( const QByteArray &md5 ); + void setReferencesIdMD5( const QByteArray &md5 ); - void setSubjectIsPrefixed( bool subjectIsPrefixed ); + void setSubjectIsPrefixed( bool subjectIsPrefixed ); - bool subjectIsPrefixed() const; + bool subjectIsPrefixed() const; - QByteArray strippedSubjectMD5() const; + QByteArray strippedSubjectMD5() const; - void setStrippedSubjectMD5( const QByteArray &md5 ); + void setStrippedSubjectMD5( const QByteArray &md5 ); - bool aboutToBeRemoved() const; + bool aboutToBeRemoved() const; - void setAboutToBeRemoved( bool aboutToBeRemoved ); + void setAboutToBeRemoved( bool aboutToBeRemoved ); - ThreadingStatus threadingStatus() const; + ThreadingStatus threadingStatus() const; - void setThreadingStatus( ThreadingStatus threadingStatus ); + void setThreadingStatus( ThreadingStatus threadingStatus ); - unsigned long uniqueId() const; + unsigned long uniqueId() const; - Akonadi::Item akonadiItem() const; - void setAkonadiItem( const Akonadi::Item &item ); + Akonadi::Item akonadiItem() const; + void setAkonadiItem( const Akonadi::Item &item ); - MessageItem * topmostMessage(); + MessageItem * topmostMessage(); - QString accessibleText( const MessageList::Core::Theme* theme, int columnIndex ); + QString accessibleText( const MessageList::Core::Theme* theme, int columnIndex ); - /** + /** * Appends the whole subtree originating at this item * to the specified list. This item is included! */ - void subTreeToList( QList< MessageItem * > &list ); + void subTreeToList( QList< MessageItem * > &list ); - // - // Colors and fonts shared by all message items. - // textColor() and font() will take the message status into account and return - // one of these. - // Call these setters only once when reading the colors from the config file. - // - static void setUnreadMessageColor( const QColor &color ); - static void setImportantMessageColor( const QColor &color ); - static void setToDoMessageColor( const QColor &color ); - static void setGeneralFont( const QFont &font ); - static void setUnreadMessageFont( const QFont &font ); - static void setImportantMessageFont( const QFont &font ); - static void setToDoMessageFont( const QFont &font ); + // + // Colors and fonts shared by all message items. + // textColor() and font() will take the message status into account and return + // one of these. + // Call these setters only once when reading the colors from the config file. + // + static void setUnreadMessageColor( const QColor &color ); + static void setImportantMessageColor( const QColor &color ); + static void setToDoMessageColor( const QColor &color ); + static void setGeneralFont( const QFont &font ); + static void setUnreadMessageFont( const QFont &font ); + static void setImportantMessageFont( const QFont &font ); + static void setToDoMessageFont( const QFont &font ); protected: - explicit MessageItem( MessageItemPrivate* dd ); + explicit MessageItem( MessageItemPrivate* dd ); private: - QString accessibleTextForField( Theme::ContentItem::Type field ); + QString accessibleTextForField( Theme::ContentItem::Type field ); - Q_DECLARE_PRIVATE( MessageItem ) + Q_DECLARE_PRIVATE( MessageItem ) }; @@ -213,7 +213,7 @@ /// A message item that can have a fake tag list and a fake annotation class MESSAGELIST_EXPORT FakeItem : public MessageItem { - public: +public: explicit FakeItem(); ~FakeItem(); @@ -227,7 +227,7 @@ /// Reimplemented to always return true virtual bool hasAnnotation() const; - private: +private: Q_DECLARE_PRIVATE( FakeItem ) }; diff -Nru kdepim-4.12.97/messagelist/core/messageitemsetmanager.cpp kdepim-4.13.0/messagelist/core/messageitemsetmanager.cpp --- kdepim-4.12.97/messagelist/core/messageitemsetmanager.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/messageitemsetmanager.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -25,22 +25,22 @@ MessageItemSetManager::MessageItemSetManager() { - mSets = new QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * >(); + mSets = new QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * >(); } MessageItemSetManager::~MessageItemSetManager() { - clearAllSets(); - delete mSets; + clearAllSets(); + delete mSets; } void MessageItemSetManager::clearAllSets() { - QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * >::ConstIterator end( mSets->constEnd() ); - for ( QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * >::ConstIterator it = mSets->constBegin(); it != end; ++it ) - delete ( *it ); + QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * >::ConstIterator end( mSets->constEnd() ); + for ( QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * >::ConstIterator it = mSets->constBegin(); it != end; ++it ) + delete ( *it ); - mSets->clear(); + mSets->clear(); } int MessageItemSetManager::setCount() const @@ -51,75 +51,75 @@ void MessageItemSetManager::removeSet( MessageItemSetReference ref ) { - QHash< MessageItem *, MessageItem * > * set = mSets->value( static_cast< unsigned long int >( ref ), 0 ); - if ( !set ) - return; - mSets->remove( static_cast< unsigned long int >( ref ) ); - delete set; + QHash< MessageItem *, MessageItem * > * set = mSets->value( static_cast< unsigned long int >( ref ), 0 ); + if ( !set ) + return; + mSets->remove( static_cast< unsigned long int >( ref ) ); + delete set; } QList< MessageItem * > MessageItemSetManager::messageItems( MessageItemSetReference ref ) { - QList< MessageItem * > ret; - QHash< MessageItem *, MessageItem * > * set = mSets->value( static_cast< unsigned long int >( ref ), 0 ); - if ( !set ) - return ret; - - QHash< MessageItem *, MessageItem * >::ConstIterator end( set->constEnd() ); - for ( QHash< MessageItem *, MessageItem * >::ConstIterator it = set->constBegin(); it != end; ++it ) - ret.append( *it ); + QList< MessageItem * > ret; + QHash< MessageItem *, MessageItem * > * set = mSets->value( static_cast< unsigned long int >( ref ), 0 ); + if ( !set ) + return ret; + + QHash< MessageItem *, MessageItem * >::ConstIterator end( set->constEnd() ); + for ( QHash< MessageItem *, MessageItem * >::ConstIterator it = set->constBegin(); it != end; ++it ) + ret.append( *it ); - return ret; + return ret; } void MessageItemSetManager::removeMessageItemFromAllSets( MessageItem * mi ) { - QList< MessageItemSetReference > setsToBeKilled; - QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * >::ConstIterator end( mSets->end()); + QList< MessageItemSetReference > setsToBeKilled; + QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * >::ConstIterator end( mSets->end()); - for ( QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * >::ConstIterator it = mSets->constBegin(); it != end; ++it ) - { - ( *it )->remove( mi ); - if ( ( *it )->isEmpty() ) - setsToBeKilled.append( it.key() ); - } - - QList< MessageItemSetReference >::ConstIterator endit2( setsToBeKilled.constEnd() ); - for ( QList< MessageItemSetReference >::ConstIterator it2 = setsToBeKilled.constBegin(); it2 != endit2; ++it2 ) - removeSet( *it2 ); + for ( QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * >::ConstIterator it = mSets->constBegin(); it != end; ++it ) + { + ( *it )->remove( mi ); + if ( ( *it )->isEmpty() ) + setsToBeKilled.append( it.key() ); + } + + QList< MessageItemSetReference >::ConstIterator endit2( setsToBeKilled.constEnd() ); + for ( QList< MessageItemSetReference >::ConstIterator it2 = setsToBeKilled.constBegin(); it2 != endit2; ++it2 ) + removeSet( *it2 ); } MessageItemSetReference MessageItemSetManager::createSet() { - static unsigned long int uNextId = 0; - uNextId++; - - QHash< MessageItem *, MessageItem * > * set = mSets->value( uNextId, 0 ); + static unsigned long int uNextId = 0; + uNextId++; - // Here we assume that having 2^32 sets is impossible - // (that would be _at_least_ 2^32 * 8 bytes of allocated memory which is - // quite a lot...) + QHash< MessageItem *, MessageItem * > * set = mSets->value( uNextId, 0 ); - while( set ) - { - uNextId++; - set = mSets->value( uNextId, 0 ); - } + // Here we assume that having 2^32 sets is impossible + // (that would be _at_least_ 2^32 * 8 bytes of allocated memory which is + // quite a lot...) + + while( set ) + { + uNextId++; + set = mSets->value( uNextId, 0 ); + } - set = new QHash< MessageItem *, MessageItem * >(); - mSets->insert( uNextId, set ); + set = new QHash< MessageItem *, MessageItem * >(); + mSets->insert( uNextId, set ); - return static_cast< MessageItemSetReference >( uNextId ); + return static_cast< MessageItemSetReference >( uNextId ); } bool MessageItemSetManager::addMessageItem( MessageItemSetReference ref, MessageItem * mi ) { - QHash< MessageItem *, MessageItem * > * set = mSets->value( static_cast< unsigned long int >( ref ), 0 ); - if ( !set ) - return false; + QHash< MessageItem *, MessageItem * > * set = mSets->value( static_cast< unsigned long int >( ref ), 0 ); + if ( !set ) + return false; - set->insert( mi, mi ); + set->insert( mi, mi ); - return true; + return true; } diff -Nru kdepim-4.12.97/messagelist/core/messageitemsetmanager.h kdepim-4.13.0/messagelist/core/messageitemsetmanager.h --- kdepim-4.12.97/messagelist/core/messageitemsetmanager.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/messageitemsetmanager.h 2014-04-10 07:40:20.000000000 +0000 @@ -48,20 +48,20 @@ class MessageItemSetManager { public: - MessageItemSetManager(); - ~MessageItemSetManager(); + MessageItemSetManager(); + ~MessageItemSetManager(); private: - QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * > * mSets; + QHash< MessageItemSetReference, QHash< MessageItem *, MessageItem * > * > * mSets; public: - void clearAllSets(); - int setCount() const; - void removeSet( MessageItemSetReference ref ); - void removeMessageItemFromAllSets( MessageItem * mi ); - QList< MessageItem * > messageItems( MessageItemSetReference ref ); - MessageItemSetReference createSet(); - bool addMessageItem( MessageItemSetReference ref, MessageItem * mi ); + void clearAllSets(); + int setCount() const; + void removeSet( MessageItemSetReference ref ); + void removeMessageItemFromAllSets( MessageItem * mi ); + QList< MessageItem * > messageItems( MessageItemSetReference ref ); + MessageItemSetReference createSet(); + bool addMessageItem( MessageItemSetReference ref, MessageItem * mi ); }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/model.cpp kdepim-4.13.0/messagelist/core/model.cpp --- kdepim-4.12.97/messagelist/core/model.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/model.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -154,105 +154,105 @@ */ class ViewItemJob { -public: - enum Pass - { - Pass1Fill = 0, ///< Build threading caches, *TRY* to do some threading, try to attach something to the view - Pass1Cleanup = 1, ///< Kill messages, build list of orphans - Pass1Update = 2, ///< Update messages - Pass2 = 3, ///< Thread everything by using caches, try to attach more to the view - Pass3 = 4, ///< Do more threading (this time try to guess), try to attach more to the view - Pass4 = 5, ///< Attach anything is still unattacched - Pass5 = 6, ///< Eventually Re-sort group headers and remove the empty ones - LastIndex = 7 ///< Keep this at the end, needed to get the size of the enum - }; -private: - // Data for "View Fill" jobs - int mStartIndex; ///< The first index (in the underlying storage) of this job - int mCurrentIndex; ///< The current index (in the underlying storage) of this job - int mEndIndex; ///< The last index (in the underlying storage) of this job - - // Data for "View Cleanup" jobs - QList< ModelInvariantIndex * > * mInvariantIndexList; ///< Owned list of shallow pointers - - // Common data - - // The maximum time that we can spend "at once" inside viewItemJobStep() (milliseconds) - // The bigger this value, the larger chunks of work we do at once and less the time - // we loose in "breaking and resuming" the job. On the other side large values tend - // to make the view less responsive up to a "freeze" perception if this value is larger - // than 2000. - int mChunkTimeout; - - // The interval between two fillView steps. The larger the interval, the more interactivity - // we have. The shorter the interval the more work we get done per second. - int mIdleInterval; - - // The minimum number of messages we process in every viewItemJobStep() call - // The larger this value the less time we loose in checking the timeout every N messages. - // On the other side, making this very large may make the view less responsive - // if we're processing very few messages at a time and very high values (say > 10000) may - // eventually make our job unbreakable until the end. - int mMessageCheckCount; - Pass mCurrentPass; - - // If this parameter is true then this job uses a "disconnected" UI. - // It's FAR faster since we don't need to call beginInsertRows()/endInsertRows() - // and we simply emit a layoutChanged() at the end. It can be done only as the first - // job though: subsequent jobs can't use layoutChanged() as it looses the expanded - // state of items. - bool mDisconnectUI; -public: - /** + public: + enum Pass + { + Pass1Fill = 0, ///< Build threading caches, *TRY* to do some threading, try to attach something to the view + Pass1Cleanup = 1, ///< Kill messages, build list of orphans + Pass1Update = 2, ///< Update messages + Pass2 = 3, ///< Thread everything by using caches, try to attach more to the view + Pass3 = 4, ///< Do more threading (this time try to guess), try to attach more to the view + Pass4 = 5, ///< Attach anything is still unattacched + Pass5 = 6, ///< Eventually Re-sort group headers and remove the empty ones + LastIndex = 7 ///< Keep this at the end, needed to get the size of the enum + }; + private: + // Data for "View Fill" jobs + int mStartIndex; ///< The first index (in the underlying storage) of this job + int mCurrentIndex; ///< The current index (in the underlying storage) of this job + int mEndIndex; ///< The last index (in the underlying storage) of this job + + // Data for "View Cleanup" jobs + QList< ModelInvariantIndex * > * mInvariantIndexList; ///< Owned list of shallow pointers + + // Common data + + // The maximum time that we can spend "at once" inside viewItemJobStep() (milliseconds) + // The bigger this value, the larger chunks of work we do at once and less the time + // we loose in "breaking and resuming" the job. On the other side large values tend + // to make the view less responsive up to a "freeze" perception if this value is larger + // than 2000. + int mChunkTimeout; + + // The interval between two fillView steps. The larger the interval, the more interactivity + // we have. The shorter the interval the more work we get done per second. + int mIdleInterval; + + // The minimum number of messages we process in every viewItemJobStep() call + // The larger this value the less time we loose in checking the timeout every N messages. + // On the other side, making this very large may make the view less responsive + // if we're processing very few messages at a time and very high values (say > 10000) may + // eventually make our job unbreakable until the end. + int mMessageCheckCount; + Pass mCurrentPass; + + // If this parameter is true then this job uses a "disconnected" UI. + // It's FAR faster since we don't need to call beginInsertRows()/endInsertRows() + // and we simply emit a layoutChanged() at the end. It can be done only as the first + // job though: subsequent jobs can't use layoutChanged() as it looses the expanded + // state of items. + bool mDisconnectUI; + public: + /** * Creates a "View Fill" operation job */ - ViewItemJob( int startIndex, int endIndex, int chunkTimeout, int idleInterval, int messageCheckCount, bool disconnectUI = false ) - : mStartIndex( startIndex ), mCurrentIndex( startIndex ), mEndIndex( endIndex ), - mInvariantIndexList( 0 ), - mChunkTimeout( chunkTimeout ), mIdleInterval( idleInterval ), - mMessageCheckCount( messageCheckCount ), mCurrentPass( Pass1Fill ), - mDisconnectUI( disconnectUI ) {} + ViewItemJob( int startIndex, int endIndex, int chunkTimeout, int idleInterval, int messageCheckCount, bool disconnectUI = false ) + : mStartIndex( startIndex ), mCurrentIndex( startIndex ), mEndIndex( endIndex ), + mInvariantIndexList( 0 ), + mChunkTimeout( chunkTimeout ), mIdleInterval( idleInterval ), + mMessageCheckCount( messageCheckCount ), mCurrentPass( Pass1Fill ), + mDisconnectUI( disconnectUI ) {} - /** + /** * Creates a "View Cleanup" or "View Update" operation job */ - ViewItemJob( Pass pass, QList< ModelInvariantIndex * > * invariantIndexList, int chunkTimeout, int idleInterval, int messageCheckCount ) - : mStartIndex( 0 ), mCurrentIndex( 0 ), mEndIndex( invariantIndexList->count() - 1 ), - mInvariantIndexList( invariantIndexList ), - mChunkTimeout( chunkTimeout ), mIdleInterval( idleInterval ), - mMessageCheckCount( messageCheckCount ), mCurrentPass( pass ), - mDisconnectUI( false ) {} - - ~ViewItemJob() - { - delete mInvariantIndexList; - } -public: - int startIndex() const + ViewItemJob( Pass pass, QList< ModelInvariantIndex * > * invariantIndexList, int chunkTimeout, int idleInterval, int messageCheckCount ) + : mStartIndex( 0 ), mCurrentIndex( 0 ), mEndIndex( invariantIndexList->count() - 1 ), + mInvariantIndexList( invariantIndexList ), + mChunkTimeout( chunkTimeout ), mIdleInterval( idleInterval ), + mMessageCheckCount( messageCheckCount ), mCurrentPass( pass ), + mDisconnectUI( false ) {} + + ~ViewItemJob() + { + delete mInvariantIndexList; + } + public: + int startIndex() const { return mStartIndex; } - void setStartIndex( int startIndex ) + void setStartIndex( int startIndex ) { mStartIndex = startIndex; mCurrentIndex = startIndex; } - int currentIndex() const + int currentIndex() const { return mCurrentIndex; } - void setCurrentIndex( int currentIndex ) + void setCurrentIndex( int currentIndex ) { mCurrentIndex = currentIndex; } - int endIndex() const + int endIndex() const { return mEndIndex; } - void setEndIndex( int endIndex ) + void setEndIndex( int endIndex ) { mEndIndex = endIndex; } - Pass currentPass() const + Pass currentPass() const { return mCurrentPass; } - void setCurrentPass( Pass pass ) + void setCurrentPass( Pass pass ) { mCurrentPass = pass; } - int idleInterval() const + int idleInterval() const { return mIdleInterval; } - int chunkTimeout() const + int chunkTimeout() const { return mChunkTimeout; } - int messageCheckCount() const + int messageCheckCount() const { return mMessageCheckCount; } - QList< ModelInvariantIndex * > * invariantIndexList() const + QList< ModelInvariantIndex * > * invariantIndexList() const { return mInvariantIndexList; } - bool disconnectUI() const + bool disconnectUI() const { return mDisconnectUI; } }; @@ -263,646 +263,646 @@ using namespace MessageList::Core; Model::Model( View *pParent ) - : QAbstractItemModel( pParent ), d( new ModelPrivate( this ) ) + : QAbstractItemModel( pParent ), d( new ModelPrivate( this ) ) { - d->mRecursionCounterForReset = 0; - d->mStorageModel = 0; - d->mView = pParent; - d->mAggregation = 0; - d->mTheme = 0; - d->mSortOrder = 0; - d->mFilter = 0; - d->mPersistentSetManager = 0; - d->mInLengthyJobBatch = false; - d->mLastSelectedMessageInFolder = 0; - d->mLoading = false; - - d->mRootItem = new Item( Item::InvisibleRoot ); - d->mRootItem->setViewable( 0, true ); - - d->mFillStepTimer.setSingleShot( true ); - d->mInvariantRowMapper = new ModelInvariantRowMapper(); - d->mModelForItemFunctions= this; - connect( &d->mFillStepTimer, SIGNAL(timeout()), - SLOT(viewItemJobStep()) ); - - d->mCachedTodayLabel = i18n( "Today" ); - d->mCachedYesterdayLabel = i18n( "Yesterday" ); - d->mCachedUnknownLabel = i18nc( "Unknown date", - "Unknown" ); - d->mCachedLastWeekLabel = i18n( "Last Week" ); - d->mCachedTwoWeeksAgoLabel = i18n( "Two Weeks Ago" ); - d->mCachedThreeWeeksAgoLabel = i18n( "Three Weeks Ago" ); - d->mCachedFourWeeksAgoLabel = i18n( "Four Weeks Ago" ); - d->mCachedFiveWeeksAgoLabel = i18n( "Five Weeks Ago" ); - - d->mCachedWatchedOrIgnoredStatusBits = Akonadi::MessageStatus::statusIgnored().toQInt32() | Akonadi::MessageStatus::statusWatched().toQInt32(); - - - connect( _k_heartBeatTimer, SIGNAL(timeout()), - this, SLOT(checkIfDateChanged()) ); - - if ( !_k_heartBeatTimer->isActive() ) { // First model starts it - _k_heartBeatTimer->start( 60000 ); // 1 minute - } + d->mRecursionCounterForReset = 0; + d->mStorageModel = 0; + d->mView = pParent; + d->mAggregation = 0; + d->mTheme = 0; + d->mSortOrder = 0; + d->mFilter = 0; + d->mPersistentSetManager = 0; + d->mInLengthyJobBatch = false; + d->mLastSelectedMessageInFolder = 0; + d->mLoading = false; + + d->mRootItem = new Item( Item::InvisibleRoot ); + d->mRootItem->setViewable( 0, true ); + + d->mFillStepTimer.setSingleShot( true ); + d->mInvariantRowMapper = new ModelInvariantRowMapper(); + d->mModelForItemFunctions= this; + connect( &d->mFillStepTimer, SIGNAL(timeout()), + SLOT(viewItemJobStep()) ); + + d->mCachedTodayLabel = i18n( "Today" ); + d->mCachedYesterdayLabel = i18n( "Yesterday" ); + d->mCachedUnknownLabel = i18nc( "Unknown date", + "Unknown" ); + d->mCachedLastWeekLabel = i18n( "Last Week" ); + d->mCachedTwoWeeksAgoLabel = i18n( "Two Weeks Ago" ); + d->mCachedThreeWeeksAgoLabel = i18n( "Three Weeks Ago" ); + d->mCachedFourWeeksAgoLabel = i18n( "Four Weeks Ago" ); + d->mCachedFiveWeeksAgoLabel = i18n( "Five Weeks Ago" ); + + d->mCachedWatchedOrIgnoredStatusBits = Akonadi::MessageStatus::statusIgnored().toQInt32() | Akonadi::MessageStatus::statusWatched().toQInt32(); + + + connect( _k_heartBeatTimer, SIGNAL(timeout()), + this, SLOT(checkIfDateChanged()) ); + + if ( !_k_heartBeatTimer->isActive() ) { // First model starts it + _k_heartBeatTimer->start( 60000 ); // 1 minute + } } Model::~Model() { - setStorageModel( 0 ); + setStorageModel( 0 ); - d->clearJobList(); - d->mOldestItem = 0; - d->mNewestItem = 0; - d->clearUnassignedMessageLists(); - d->clearOrphanChildrenHash(); - d->clearThreadingCacheMessageSubjectMD5ToMessageItem(); - delete d->mPersistentSetManager; - // Delete the invariant row mapper before removing the items. - // It's faster since the items will not need to call the invariant - delete d->mInvariantRowMapper; - delete d->mRootItem; + d->clearJobList(); + d->mOldestItem = 0; + d->mNewestItem = 0; + d->clearUnassignedMessageLists(); + d->clearOrphanChildrenHash(); + d->clearThreadingCacheMessageSubjectMD5ToMessageItem(); + delete d->mPersistentSetManager; + // Delete the invariant row mapper before removing the items. + // It's faster since the items will not need to call the invariant + delete d->mInvariantRowMapper; + delete d->mRootItem; - delete d; + delete d; } void Model::setAggregation( const Aggregation * aggregation ) { - d->mAggregation = aggregation; - d->mView->setRootIsDecorated( ( d->mAggregation->grouping() == Aggregation::NoGrouping ) && - ( d->mAggregation->threading() != Aggregation::NoThreading ) ); + d->mAggregation = aggregation; + d->mView->setRootIsDecorated( ( d->mAggregation->grouping() == Aggregation::NoGrouping ) && + ( d->mAggregation->threading() != Aggregation::NoThreading ) ); } void Model::setTheme( const Theme * theme ) { - d->mTheme = theme; + d->mTheme = theme; } void Model::setSortOrder( const SortOrder * sortOrder ) { - d->mSortOrder = sortOrder; + d->mSortOrder = sortOrder; } const SortOrder * Model::sortOrder() const { - return d->mSortOrder; + return d->mSortOrder; } void Model::setFilter( const Filter *filter ) { - d->mFilter = filter; + d->mFilter = filter; - if (d->mFilter) - connect( d->mFilter, SIGNAL(finished()), this, SLOT(slotApplyFilter()) ); + if (d->mFilter) + connect( d->mFilter, SIGNAL(finished()), this, SLOT(slotApplyFilter()) ); - d->slotApplyFilter(); + d->slotApplyFilter(); } void ModelPrivate::slotApplyFilter() { - QList< Item * > * childList = mRootItem->childItems(); - if ( !childList ) - return; - - QModelIndex idx; // invalid - - QApplication::setOverrideCursor( Qt::WaitCursor ); - QList< Item * >::ConstIterator end = childList->constEnd(); - for ( QList< Item * >::ConstIterator it = childList->constBegin(); it != end; ++it ) - applyFilterToSubtree( *it, idx ); + QList< Item * > * childList = mRootItem->childItems(); + if ( !childList ) + return; + + QModelIndex idx; // invalid - QApplication::restoreOverrideCursor(); + QApplication::setOverrideCursor( Qt::WaitCursor ); + QList< Item * >::ConstIterator end = childList->constEnd(); + for ( QList< Item * >::ConstIterator it = childList->constBegin(); it != end; ++it ) + applyFilterToSubtree( *it, idx ); + + QApplication::restoreOverrideCursor(); } bool ModelPrivate::applyFilterToSubtree( Item * item, const QModelIndex &parentIndex ) { - // This function applies the current filter (eventually empty) - // to a message tree starting at "item". + // This function applies the current filter (eventually empty) + // to a message tree starting at "item". - if ( !mModelForItemFunctions ) { - kWarning() << "Cannot apply filter, the UI must be not disconnected."; - return true; - } - Q_ASSERT( item ); // the item must obviously be valid - Q_ASSERT( item->isViewable() ); // the item must be viewable + if ( !mModelForItemFunctions ) { + kWarning() << "Cannot apply filter, the UI must be not disconnected."; + return true; + } + Q_ASSERT( item ); // the item must obviously be valid + Q_ASSERT( item->isViewable() ); // the item must be viewable - // Apply to children first + // Apply to children first - QList< Item * > * childList = item->childItems(); + QList< Item * > * childList = item->childItems(); - bool childrenMatch = false; + bool childrenMatch = false; - QModelIndex thisIndex = q->index( item, 0 ); + QModelIndex thisIndex = q->index( item, 0 ); - if ( childList ) - { - QList< Item * >::ConstIterator end( childList->constEnd() ); - for ( QList< Item * >::ConstIterator it = childList->constBegin(); it != end; ++it ) + if ( childList ) { - if ( applyFilterToSubtree( *it, thisIndex ) ) - childrenMatch = true; + QList< Item * >::ConstIterator end( childList->constEnd() ); + for ( QList< Item * >::ConstIterator it = childList->constBegin(); it != end; ++it ) + { + if ( applyFilterToSubtree( *it, thisIndex ) ) + childrenMatch = true; + } } - } - if ( !mFilter ) // empty filter always matches (but does not expand items) - { - mView->setRowHidden( thisIndex.row(), parentIndex, false ); - return true; - } + if ( !mFilter ) // empty filter always matches (but does not expand items) + { + mView->setRowHidden( thisIndex.row(), parentIndex, false ); + return true; + } - if ( childrenMatch ) - { - mView->setRowHidden( thisIndex.row(), parentIndex, false ); + if ( childrenMatch ) + { + mView->setRowHidden( thisIndex.row(), parentIndex, false ); - if ( !mView->isExpanded( thisIndex ) ) - mView->expand( thisIndex ); - return true; - } + if ( !mView->isExpanded( thisIndex ) ) + mView->expand( thisIndex ); + return true; + } - if ( item->type() == Item::Message ) - { - if ( mFilter->match( ( MessageItem * )item ) ) + if ( item->type() == Item::Message ) { - mView->setRowHidden( thisIndex.row(), parentIndex, false ); - return true; - } - } // else this is a group header and it never explicitly matches + if ( mFilter->match( ( MessageItem * )item ) ) + { + mView->setRowHidden( thisIndex.row(), parentIndex, false ); + return true; + } + } // else this is a group header and it never explicitly matches - // filter doesn't match, hide the item - mView->setRowHidden( thisIndex.row(), parentIndex, true ); + // filter doesn't match, hide the item + mView->setRowHidden( thisIndex.row(), parentIndex, true ); - return false; + return false; } int Model::columnCount( const QModelIndex & parent ) const { - if ( !d->mTheme ) - return 0; - if ( parent.column() > 0 ) - return 0; - return d->mTheme->columns().count(); + if ( !d->mTheme ) + return 0; + if ( parent.column() > 0 ) + return 0; + return d->mTheme->columns().count(); } QVariant Model::data( const QModelIndex & index, int role ) const { - /// this is called only when Akonadi is using the selectionmodel - /// for item actions. since akonadi uses the ETM ItemRoles, and the - /// messagelist uses its own internal roles, here we respond - /// to the ETM ones. + /// this is called only when Akonadi is using the selectionmodel + /// for item actions. since akonadi uses the ETM ItemRoles, and the + /// messagelist uses its own internal roles, here we respond + /// to the ETM ones. - Item* item = static_cast< Item* >( index.internalPointer() ); + Item* item = static_cast< Item* >( index.internalPointer() ); - switch( role ) { - /// taken from entitytreemodel.h + switch( role ) { + /// taken from entitytreemodel.h case Qt::UserRole + 1: //EntityTreeModel::ItemIdRole - if( item->type() == MessageList::Core::Item::Message ) { - MessageItem* mItem = static_cast( item ); - return QVariant::fromValue( mItem->akonadiItem().id() ); - } else - return QVariant(); - break; + if( item->type() == MessageList::Core::Item::Message ) { + MessageItem* mItem = static_cast( item ); + return QVariant::fromValue( mItem->akonadiItem().id() ); + } else + return QVariant(); + break; case Qt::UserRole + 2: //EntityTreeModel::ItemRole - if( item->type() == MessageList::Core::Item::Message ) { - MessageItem* mItem = static_cast( item ); - return QVariant::fromValue( mItem->akonadiItem() ); - } else - return QVariant(); - break; + if( item->type() == MessageList::Core::Item::Message ) { + MessageItem* mItem = static_cast( item ); + return QVariant::fromValue( mItem->akonadiItem() ); + } else + return QVariant(); + break; case Qt::UserRole + 3: //EntityTreeModel::MimeTypeRole - if( item->type() == MessageList::Core::Item::Message ) - return QLatin1String( "message/rfc822" ); - else - return QVariant(); - break; + if( item->type() == MessageList::Core::Item::Message ) + return QLatin1String( "message/rfc822" ); + else + return QVariant(); + break; case Qt::AccessibleTextRole: - if( item->type() == MessageList::Core::Item::Message ) { - MessageItem* mItem = static_cast( item ); - return mItem->accessibleText( d->mTheme , index.column() ); - } else if ( item->type() == MessageList::Core::Item::GroupHeader ) { - if ( index.column() > 0) - return QString(); - GroupHeaderItem* hItem = static_cast( item ); - return hItem->label(); - } - return QString(); - break; + if( item->type() == MessageList::Core::Item::Message ) { + MessageItem* mItem = static_cast( item ); + return mItem->accessibleText( d->mTheme , index.column() ); + } else if ( item->type() == MessageList::Core::Item::GroupHeader ) { + if ( index.column() > 0) + return QString(); + GroupHeaderItem* hItem = static_cast( item ); + return hItem->label(); + } + return QString(); + break; default: - return QVariant(); - } + return QVariant(); + } } QVariant Model::headerData(int section, Qt::Orientation, int role) const { - if ( !d->mTheme ) - return QVariant(); + if ( !d->mTheme ) + return QVariant(); - Theme::Column * column = d->mTheme->column( section ); - if ( !column ) - return QVariant(); + Theme::Column * column = d->mTheme->column( section ); + if ( !column ) + return QVariant(); - if ( d->mStorageModel && column->isSenderOrReceiver() && - ( role == Qt::DisplayRole ) ) - { - if ( d->mStorageModelContainsOutboundMessages ) - return QVariant( i18n( "Receiver" ) ); - return QVariant( i18n( "Sender" ) ); - } - - const bool columnPixmapEmpty(column->pixmapName().isEmpty()); - if ( ( role == Qt::DisplayRole ) && columnPixmapEmpty ) - return QVariant( column->label() ); - else if ( ( role == Qt::ToolTipRole ) && !columnPixmapEmpty ) - return QVariant( column->label() ); - else if ( ( role == Qt::DecorationRole ) && !columnPixmapEmpty ) - return QVariant( KIcon( column->pixmapName() ) ); + if ( d->mStorageModel && column->isSenderOrReceiver() && + ( role == Qt::DisplayRole ) ) + { + if ( d->mStorageModelContainsOutboundMessages ) + return QVariant( i18n( "Receiver" ) ); + return QVariant( i18n( "Sender" ) ); + } - return QVariant(); + const bool columnPixmapEmpty(column->pixmapName().isEmpty()); + if ( ( role == Qt::DisplayRole ) && columnPixmapEmpty ) + return QVariant( column->label() ); + else if ( ( role == Qt::ToolTipRole ) && !columnPixmapEmpty ) + return QVariant( column->label() ); + else if ( ( role == Qt::DecorationRole ) && !columnPixmapEmpty ) + return QVariant( KIcon( column->pixmapName() ) ); + + return QVariant(); } QModelIndex Model::index( Item *item, int column ) const { - if ( !d->mModelForItemFunctions ) - return QModelIndex(); // called with disconnected UI: the item isn't known on the Qt side, yet + if ( !d->mModelForItemFunctions ) + return QModelIndex(); // called with disconnected UI: the item isn't known on the Qt side, yet + + if ( !item ) { + return QModelIndex(); + } + // FIXME: This function is a bottleneck (the caching in indexOfChildItem only works 30% of the time) + Item * par = item->parent(); + if ( !par ) + { + if ( item != d->mRootItem ) + item->dump(QString()); + return QModelIndex(); + } - if ( !item ) { - return QModelIndex(); - } - // FIXME: This function is a bottleneck (the caching in indexOfChildItem only works 30% of the time) - Item * par = item->parent(); - if ( !par ) - { - if ( item != d->mRootItem ) - item->dump(QString()); - return QModelIndex(); - } - - const int index = par->indexOfChildItem(item); - if ( index < 0 ) - return QModelIndex(); // BUG - return createIndex(index, column, item); + const int index = par->indexOfChildItem(item); + if ( index < 0 ) + return QModelIndex(); // BUG + return createIndex(index, column, item); } QModelIndex Model::index( int row, int column, const QModelIndex &parent ) const { - if ( !d->mModelForItemFunctions ) - return QModelIndex(); // called with disconnected UI: the item isn't known on the Qt side, yet + if ( !d->mModelForItemFunctions ) + return QModelIndex(); // called with disconnected UI: the item isn't known on the Qt side, yet #ifdef READD_THIS_IF_YOU_WANT_TO_PASS_MODEL_TEST - if ( column < 0 ) - return QModelIndex(); // senseless column (we could optimize by skipping this check but ModelTest from trolltech is pedantic) + if ( column < 0 ) + return QModelIndex(); // senseless column (we could optimize by skipping this check but ModelTest from trolltech is pedantic) #endif - const Item *item; - if ( parent.isValid() ) - { - item = static_cast< const Item * >( parent.internalPointer() ); - if ( !item ) - return QModelIndex(); // should never happen - } else { - item = d->mRootItem; - } - - if ( parent.column() > 0 ) - return QModelIndex(); // parent column is not 0: shouldn't have children (as per Qt documentation) - - Item * child = item->childItem( row ); - if ( !child ) - return QModelIndex(); // no such row in parent - return createIndex( row, column, child ); + const Item *item; + if ( parent.isValid() ) + { + item = static_cast< const Item * >( parent.internalPointer() ); + if ( !item ) + return QModelIndex(); // should never happen + } else { + item = d->mRootItem; + } + + if ( parent.column() > 0 ) + return QModelIndex(); // parent column is not 0: shouldn't have children (as per Qt documentation) + + Item * child = item->childItem( row ); + if ( !child ) + return QModelIndex(); // no such row in parent + return createIndex( row, column, child ); } QModelIndex Model::parent( const QModelIndex &modelIndex ) const { - Q_ASSERT( d->mModelForItemFunctions ); // should be never called with disconnected UI + Q_ASSERT( d->mModelForItemFunctions ); // should be never called with disconnected UI - if ( !modelIndex.isValid() ) - return QModelIndex(); // should never happen - Item *item = static_cast< Item * >( modelIndex.internalPointer() ); - if ( !item ) - return QModelIndex(); - Item *par = item->parent(); - if ( !par ) - return QModelIndex(); // should never happen - //return index( par, modelIndex.column() ); - return index( par, 0 ); // parents are always in column 0 (as per Qt documentation) + if ( !modelIndex.isValid() ) + return QModelIndex(); // should never happen + Item *item = static_cast< Item * >( modelIndex.internalPointer() ); + if ( !item ) + return QModelIndex(); + Item *par = item->parent(); + if ( !par ) + return QModelIndex(); // should never happen + //return index( par, modelIndex.column() ); + return index( par, 0 ); // parents are always in column 0 (as per Qt documentation) } int Model::rowCount( const QModelIndex &parent ) const { - if ( !d->mModelForItemFunctions ) - return 0; // called with disconnected UI + if ( !d->mModelForItemFunctions ) + return 0; // called with disconnected UI - const Item *item; - if ( parent.isValid() ) - { - item = static_cast< const Item * >( parent.internalPointer() ); - if ( !item ) - return 0; // should never happen - } else { - item = d->mRootItem; - } + const Item *item; + if ( parent.isValid() ) + { + item = static_cast< const Item * >( parent.internalPointer() ); + if ( !item ) + return 0; // should never happen + } else { + item = d->mRootItem; + } - if ( !item->isViewable() ) - return 0; + if ( !item->isViewable() ) + return 0; - return item->childItemCount(); + return item->childItemCount(); } class RecursionPreventer { public: - RecursionPreventer( int &counter ) - : mCounter( counter ) { mCounter++; } - ~RecursionPreventer() { mCounter--; } - bool isRecursive() const { return mCounter > 1; } + RecursionPreventer( int &counter ) + : mCounter( counter ) { mCounter++; } + ~RecursionPreventer() { mCounter--; } + bool isRecursive() const { return mCounter > 1; } private: - int &mCounter; + int &mCounter; }; StorageModel *Model::storageModel() const { - return d->mStorageModel; + return d->mStorageModel; } void ModelPrivate::clear() { - if( mFillStepTimer.isActive() ) - mFillStepTimer.stop(); + if( mFillStepTimer.isActive() ) + mFillStepTimer.stop(); - // Kill pre-selection at this stage - mPreSelectionMode = PreSelectNone; - mLastSelectedMessageInFolder = 0; - mOldestItem = 0; - mNewestItem = 0; - - // Reset the row mapper before removing items - // This is faster since the items don't need to access the mapper. - mInvariantRowMapper->modelReset(); - - clearJobList(); - clearUnassignedMessageLists(); - clearOrphanChildrenHash(); - mGroupHeaderItemHash.clear(); - mGroupHeadersThatNeedUpdate.clear(); - mThreadingCacheMessageIdMD5ToMessageItem.clear(); - mThreadingCacheMessageInReplyToIdMD5ToMessageItem.clear(); - clearThreadingCacheMessageSubjectMD5ToMessageItem(); - mViewItemJobStepChunkTimeout = 100; - mViewItemJobStepIdleInterval = 10; - mViewItemJobStepMessageCheckCount = 10; - delete mPersistentSetManager; - mPersistentSetManager = 0; - mCurrentItemToRestoreAfterViewItemJobStep = 0; + // Kill pre-selection at this stage + mPreSelectionMode = PreSelectNone; + mLastSelectedMessageInFolder = 0; + mOldestItem = 0; + mNewestItem = 0; + + // Reset the row mapper before removing items + // This is faster since the items don't need to access the mapper. + mInvariantRowMapper->modelReset(); + + clearJobList(); + clearUnassignedMessageLists(); + clearOrphanChildrenHash(); + mGroupHeaderItemHash.clear(); + mGroupHeadersThatNeedUpdate.clear(); + mThreadingCacheMessageIdMD5ToMessageItem.clear(); + mThreadingCacheMessageInReplyToIdMD5ToMessageItem.clear(); + clearThreadingCacheMessageSubjectMD5ToMessageItem(); + mViewItemJobStepChunkTimeout = 100; + mViewItemJobStepIdleInterval = 10; + mViewItemJobStepMessageCheckCount = 10; + delete mPersistentSetManager; + mPersistentSetManager = 0; + mCurrentItemToRestoreAfterViewItemJobStep = 0; - mTodayDate = QDate::currentDate(); + mTodayDate = QDate::currentDate(); // FIXME: CLEAR THE FILTER HERE AS WE CAN'T APPLY IT WITH UI DISCONNECTED! - mRootItem->killAllChildItems(); + mRootItem->killAllChildItems(); - q->reset(); - //emit headerDataChanged(); + q->reset(); + //emit headerDataChanged(); - mView->modelHasBeenReset(); - mView->selectionModel()->clearSelection(); + mView->modelHasBeenReset(); + mView->selectionModel()->clearSelection(); } void Model::setStorageModel( StorageModel *storageModel, PreSelectionMode preSelectionMode ) { - // Prevent a case of recursion when opening a folder that has a message and the folder was - // never opened before. - RecursionPreventer preventer( d->mRecursionCounterForReset ); - if ( preventer.isRecursive() ) - return; - - d->clear(); - - if ( d->mStorageModel ) { - disconnect( d->mStorageModel, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(slotStorageModelRowsInserted(QModelIndex,int,int)) ); - disconnect( d->mStorageModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(slotStorageModelRowsRemoved(QModelIndex,int,int)) ); - - disconnect( d->mStorageModel, SIGNAL(layoutChanged()), - this, SLOT(slotStorageModelLayoutChanged()) ); - disconnect( d->mStorageModel, SIGNAL(modelReset()), - this, SLOT(slotStorageModelLayoutChanged()) ); - - disconnect( d->mStorageModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(slotStorageModelDataChanged(QModelIndex,QModelIndex)) ); - disconnect( d->mStorageModel, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(slotStorageModelHeaderDataChanged(Qt::Orientation,int,int)) ); - } - - d->mStorageModel = storageModel; - - if ( !d->mStorageModel ) - return; // no folder: nothing to fill - - // Sometimes the folders need to be resurrected... - d->mStorageModel->prepareForScan(); - - d->mPreSelectionMode = preSelectionMode; - d->mStorageModelContainsOutboundMessages = d->mStorageModel->containsOutboundMessages(); - - connect( d->mStorageModel, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(slotStorageModelRowsInserted(QModelIndex,int,int)) ); - connect( d->mStorageModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(slotStorageModelRowsRemoved(QModelIndex,int,int)) ); - - connect( d->mStorageModel, SIGNAL(layoutChanged()), - this, SLOT(slotStorageModelLayoutChanged()) ); - connect( d->mStorageModel, SIGNAL(modelReset()), - this, SLOT(slotStorageModelLayoutChanged()) ); - - connect( d->mStorageModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(slotStorageModelDataChanged(QModelIndex,QModelIndex)) ); - connect( d->mStorageModel, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(slotStorageModelHeaderDataChanged(Qt::Orientation,int,int)) ); - - if ( d->mStorageModel->rowCount() == 0 ) - return; // folder empty: nothing to fill - - // Here we use different strategies based on user preference and the folder size. - // The knobs we can tune are: - // - // - The number of jobs used to scan the whole folder and their order - // - // There are basically two approaches to this. One is the "single big job" - // approach. It scans the folder from the beginning to the end in a single job - // entry. The job passes are done only once. It's advantage is that it's simplier - // and it's less likely to generate imperfect parent threadings. The bad - // side is that since the folders are "sort of" date ordered then the most interesting - // messages show up at the end of the work. Not nice for large folders. - // The other approach uses two jobs. This is a bit slower but smarter strategy. - // First we scan the latest 1000 messages and *then* take care of the older ones. - // This will show up the most interesting messages almost immediately. (Well... - // All this assuming that the underlying storage always appends the newly arrived messages) - // The strategy is slower since it generates some imperfect parent threadings which must be - // adjusted by the second job. For instance, in my kernel mailing list folder this "smart" approach - // generates about 150 additional imperfectly threaded children... but the "today" - // messages show up almost immediately. The two-chunk job also makes computing - // the percentage user feedback a little harder and might break some optimization - // in the insertions (we're able to optimize appends and prepends but a chunked - // job is likely to split our work at a boundary where messages are always inserted - // in the middle of the list). - // - // - The maximum time to spend inside a single job step - // - // The larger this time, the greater the number of messages per second that this - // engine can process but also greater time with frozen UI -> less interactivity. - // Reasonable values start at 50 msecs. Values larger than 300 msecs are very likely - // to be percieved by the user as UI non-reactivity. - // - // - The number of messages processed in each job step subchunk. - // - // A job subchunk is processed without checking the maximum time above. This means - // that each job step will process at least the number of messages specified by this value. - // Very low values mean that we respect the maximum time very carefully but we also - // waste time to check if we ran out of time :) - // Very high values are likely to cause the engine to not respect the maximum step time. - // Reasonable values go from 5 to 100. - // - // - The "idle" time between two steps - // - // The lower this time, the greater the number of messages per second that this - // engine can process but also lower time for the UI to process events -> less interactivity. - // A value of 0 here means that Qt will trigger the timer as soon as it has some - // idle time to spend. UI events will be still processed but slowdowns are possible. - // 0 is reasonable though. Values larger than 200 will tend to make the total job - // completion times high. - // - - // If we have no filter it seems that we can apply a huge optimization. - // We disconnect the UI for the first huge filling job. This allows us - // to save the extremely expensive beginInsertRows()/endInsertRows() calls - // and call a single layoutChanged() at the end. This slows down a lot item - // expansion. But on the other side if only few items need to be expanded - // then this strategy is better. If filtering is enabled then this strategy - // isn't applicable (because filtering requires interaction with the UI - // while the data is loading). - - // So... - - // For the very first small chunk it's ok to work with disconnected UI as long - // as we have no filter. The first small chunk is always 1000 messages, so - // even if all of them are expanded, it's still somewhat acceptable. - bool canDoFirstSmallChunkWithDisconnectedUI = !d->mFilter; - - // Larger works need a bigger condition: few messages must be expanded in the end. - bool canDoJobWithDisconnectedUI = - // we have no filter - !d->mFilter && - ( - // we do no threading at all - ( d->mAggregation->threading() == Aggregation::NoThreading ) || - // or we never expand threads - ( d->mAggregation->threadExpandPolicy() == Aggregation::NeverExpandThreads ) || - // or we expand threads but we'll be going to expand really only a few + // Prevent a case of recursion when opening a folder that has a message and the folder was + // never opened before. + RecursionPreventer preventer( d->mRecursionCounterForReset ); + if ( preventer.isRecursive() ) + return; + + d->clear(); + + if ( d->mStorageModel ) { + disconnect( d->mStorageModel, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(slotStorageModelRowsInserted(QModelIndex,int,int)) ); + disconnect( d->mStorageModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(slotStorageModelRowsRemoved(QModelIndex,int,int)) ); + + disconnect( d->mStorageModel, SIGNAL(layoutChanged()), + this, SLOT(slotStorageModelLayoutChanged()) ); + disconnect( d->mStorageModel, SIGNAL(modelReset()), + this, SLOT(slotStorageModelLayoutChanged()) ); + + disconnect( d->mStorageModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(slotStorageModelDataChanged(QModelIndex,QModelIndex)) ); + disconnect( d->mStorageModel, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), + this, SLOT(slotStorageModelHeaderDataChanged(Qt::Orientation,int,int)) ); + } + + d->mStorageModel = storageModel; + + if ( !d->mStorageModel ) + return; // no folder: nothing to fill + + // Sometimes the folders need to be resurrected... + d->mStorageModel->prepareForScan(); + + d->mPreSelectionMode = preSelectionMode; + d->mStorageModelContainsOutboundMessages = d->mStorageModel->containsOutboundMessages(); + + connect( d->mStorageModel, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(slotStorageModelRowsInserted(QModelIndex,int,int)) ); + connect( d->mStorageModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(slotStorageModelRowsRemoved(QModelIndex,int,int)) ); + + connect( d->mStorageModel, SIGNAL(layoutChanged()), + this, SLOT(slotStorageModelLayoutChanged()) ); + connect( d->mStorageModel, SIGNAL(modelReset()), + this, SLOT(slotStorageModelLayoutChanged()) ); + + connect( d->mStorageModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(slotStorageModelDataChanged(QModelIndex,QModelIndex)) ); + connect( d->mStorageModel, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), + this, SLOT(slotStorageModelHeaderDataChanged(Qt::Orientation,int,int)) ); + + if ( d->mStorageModel->rowCount() == 0 ) + return; // folder empty: nothing to fill + + // Here we use different strategies based on user preference and the folder size. + // The knobs we can tune are: + // + // - The number of jobs used to scan the whole folder and their order + // + // There are basically two approaches to this. One is the "single big job" + // approach. It scans the folder from the beginning to the end in a single job + // entry. The job passes are done only once. It's advantage is that it's simplier + // and it's less likely to generate imperfect parent threadings. The bad + // side is that since the folders are "sort of" date ordered then the most interesting + // messages show up at the end of the work. Not nice for large folders. + // The other approach uses two jobs. This is a bit slower but smarter strategy. + // First we scan the latest 1000 messages and *then* take care of the older ones. + // This will show up the most interesting messages almost immediately. (Well... + // All this assuming that the underlying storage always appends the newly arrived messages) + // The strategy is slower since it generates some imperfect parent threadings which must be + // adjusted by the second job. For instance, in my kernel mailing list folder this "smart" approach + // generates about 150 additional imperfectly threaded children... but the "today" + // messages show up almost immediately. The two-chunk job also makes computing + // the percentage user feedback a little harder and might break some optimization + // in the insertions (we're able to optimize appends and prepends but a chunked + // job is likely to split our work at a boundary where messages are always inserted + // in the middle of the list). + // + // - The maximum time to spend inside a single job step + // + // The larger this time, the greater the number of messages per second that this + // engine can process but also greater time with frozen UI -> less interactivity. + // Reasonable values start at 50 msecs. Values larger than 300 msecs are very likely + // to be percieved by the user as UI non-reactivity. + // + // - The number of messages processed in each job step subchunk. + // + // A job subchunk is processed without checking the maximum time above. This means + // that each job step will process at least the number of messages specified by this value. + // Very low values mean that we respect the maximum time very carefully but we also + // waste time to check if we ran out of time :) + // Very high values are likely to cause the engine to not respect the maximum step time. + // Reasonable values go from 5 to 100. + // + // - The "idle" time between two steps + // + // The lower this time, the greater the number of messages per second that this + // engine can process but also lower time for the UI to process events -> less interactivity. + // A value of 0 here means that Qt will trigger the timer as soon as it has some + // idle time to spend. UI events will be still processed but slowdowns are possible. + // 0 is reasonable though. Values larger than 200 will tend to make the total job + // completion times high. + // + + // If we have no filter it seems that we can apply a huge optimization. + // We disconnect the UI for the first huge filling job. This allows us + // to save the extremely expensive beginInsertRows()/endInsertRows() calls + // and call a single layoutChanged() at the end. This slows down a lot item + // expansion. But on the other side if only few items need to be expanded + // then this strategy is better. If filtering is enabled then this strategy + // isn't applicable (because filtering requires interaction with the UI + // while the data is loading). + + // So... + + // For the very first small chunk it's ok to work with disconnected UI as long + // as we have no filter. The first small chunk is always 1000 messages, so + // even if all of them are expanded, it's still somewhat acceptable. + bool canDoFirstSmallChunkWithDisconnectedUI = !d->mFilter; + + // Larger works need a bigger condition: few messages must be expanded in the end. + bool canDoJobWithDisconnectedUI = + // we have no filter + !d->mFilter && ( - // so we don't expand them all - ( d->mAggregation->threadExpandPolicy() != Aggregation::AlwaysExpandThreads ) && - // and we'd expand only a few in fact - ( d->mStorageModel->initialUnreadRowCountGuess() < 1000 ) - ) - ); + // we do no threading at all + ( d->mAggregation->threading() == Aggregation::NoThreading ) || + // or we never expand threads + ( d->mAggregation->threadExpandPolicy() == Aggregation::NeverExpandThreads ) || + // or we expand threads but we'll be going to expand really only a few + ( + // so we don't expand them all + ( d->mAggregation->threadExpandPolicy() != Aggregation::AlwaysExpandThreads ) && + // and we'd expand only a few in fact + ( d->mStorageModel->initialUnreadRowCountGuess() < 1000 ) + ) + ); - switch ( d->mAggregation->fillViewStrategy() ) - { + switch ( d->mAggregation->fillViewStrategy() ) + { case Aggregation::FavorInteractivity: - // favor interactivity - if ( ( !canDoJobWithDisconnectedUI ) && ( d->mStorageModel->rowCount() > 3000 ) ) // empiric value - { - // First a small job with the most recent messages. Large chunk, small (but non zero) idle interval - // and a larger number of messages to process at once. - ViewItemJob * job1 = new ViewItemJob( d->mStorageModel->rowCount() - 1000, d->mStorageModel->rowCount() - 1, 200, 20, 100, canDoFirstSmallChunkWithDisconnectedUI ); - d->mViewItemJobs.append( job1 ); - // Then a larger job with older messages. Small chunk, bigger idle interval, small number of messages to - // process at once. - ViewItemJob * job2 = new ViewItemJob( 0, d->mStorageModel->rowCount() - 1001, 100, 50, 10, false ); - d->mViewItemJobs.append( job2 ); - - // We could even extremize this by splitting the folder in several - // chunks and scanning them from the newest to the oldest... but the overhead - // due to imperfectly threaded children would be probably too big. - } else { - // small folder or can be done with disconnected UI: single chunk work. - // Lag the CPU a bit more but not too much to destroy even the earliest interactivity. - ViewItemJob * job = new ViewItemJob( 0, d->mStorageModel->rowCount() - 1, 150, 30, 30, canDoJobWithDisconnectedUI ); - d->mViewItemJobs.append( job ); - } - break; + // favor interactivity + if ( ( !canDoJobWithDisconnectedUI ) && ( d->mStorageModel->rowCount() > 3000 ) ) // empiric value + { + // First a small job with the most recent messages. Large chunk, small (but non zero) idle interval + // and a larger number of messages to process at once. + ViewItemJob * job1 = new ViewItemJob( d->mStorageModel->rowCount() - 1000, d->mStorageModel->rowCount() - 1, 200, 20, 100, canDoFirstSmallChunkWithDisconnectedUI ); + d->mViewItemJobs.append( job1 ); + // Then a larger job with older messages. Small chunk, bigger idle interval, small number of messages to + // process at once. + ViewItemJob * job2 = new ViewItemJob( 0, d->mStorageModel->rowCount() - 1001, 100, 50, 10, false ); + d->mViewItemJobs.append( job2 ); + + // We could even extremize this by splitting the folder in several + // chunks and scanning them from the newest to the oldest... but the overhead + // due to imperfectly threaded children would be probably too big. + } else { + // small folder or can be done with disconnected UI: single chunk work. + // Lag the CPU a bit more but not too much to destroy even the earliest interactivity. + ViewItemJob * job = new ViewItemJob( 0, d->mStorageModel->rowCount() - 1, 150, 30, 30, canDoJobWithDisconnectedUI ); + d->mViewItemJobs.append( job ); + } + break; case Aggregation::FavorSpeed: - // More batchy jobs, still interactive to a certain degree - if ( ( !canDoJobWithDisconnectedUI ) && ( d->mStorageModel->rowCount() > 3000 ) ) // empiric value - { - // large folder, but favor speed - ViewItemJob * job1 = new ViewItemJob( d->mStorageModel->rowCount() - 1000, d->mStorageModel->rowCount() - 1, 250, 0, 100, canDoFirstSmallChunkWithDisconnectedUI ); - d->mViewItemJobs.append( job1 ); - ViewItemJob * job2 = new ViewItemJob( 0, d->mStorageModel->rowCount() - 1001, 200, 0, 10, false ); - d->mViewItemJobs.append( job2 ); - } else { - // small folder or can be done with disconnected UI and favor speed: single chunk work. - // Lag the CPU more, get more work done - ViewItemJob * job = new ViewItemJob( 0, d->mStorageModel->rowCount() - 1, 250, 0, 100, canDoJobWithDisconnectedUI ); - d->mViewItemJobs.append( job ); - } - break; + // More batchy jobs, still interactive to a certain degree + if ( ( !canDoJobWithDisconnectedUI ) && ( d->mStorageModel->rowCount() > 3000 ) ) // empiric value + { + // large folder, but favor speed + ViewItemJob * job1 = new ViewItemJob( d->mStorageModel->rowCount() - 1000, d->mStorageModel->rowCount() - 1, 250, 0, 100, canDoFirstSmallChunkWithDisconnectedUI ); + d->mViewItemJobs.append( job1 ); + ViewItemJob * job2 = new ViewItemJob( 0, d->mStorageModel->rowCount() - 1001, 200, 0, 10, false ); + d->mViewItemJobs.append( job2 ); + } else { + // small folder or can be done with disconnected UI and favor speed: single chunk work. + // Lag the CPU more, get more work done + ViewItemJob * job = new ViewItemJob( 0, d->mStorageModel->rowCount() - 1, 250, 0, 100, canDoJobWithDisconnectedUI ); + d->mViewItemJobs.append( job ); + } + break; case Aggregation::BatchNoInteractivity: { - // one large job, never interrupt, block UI - ViewItemJob * job = new ViewItemJob( 0, d->mStorageModel->rowCount() - 1, 60000, 0, 100000, canDoJobWithDisconnectedUI ); - d->mViewItemJobs.append( job ); + // one large job, never interrupt, block UI + ViewItemJob * job = new ViewItemJob( 0, d->mStorageModel->rowCount() - 1, 60000, 0, 100000, canDoJobWithDisconnectedUI ); + d->mViewItemJobs.append( job ); } - break; + break; default: - kWarning() << "Unrecognized fill view strategy"; - Q_ASSERT( false ); - break; - } + kWarning() << "Unrecognized fill view strategy"; + Q_ASSERT( false ); + break; + } - d->mLoading = true; + d->mLoading = true; - d->viewItemJobStep(); + d->viewItemJobStep(); } void ModelPrivate::checkIfDateChanged() { - // This function is called by MessageList::Core::Manager once in a while (every 1 minute or sth). - // It is used to check if the current date has changed (with respect to mTodayDate). - // - // Our message items cache the formatted dates (as formatting them - // on the fly would be too expensive). We also cache the labels of the groups which often display dates. - // When the date changes we would need to fix all these strings. - // - // A dedicated algorithm to refresh the labels of the items would be either too complex - // or would block on large trees. Fixing the labels of the groups is also quite hard... - // - // So to keep the things simple we just reload the view. - - if ( !mStorageModel ) - return; // nothing to do - - if ( mLoading ) - return; // not now + // This function is called by MessageList::Core::Manager once in a while (every 1 minute or sth). + // It is used to check if the current date has changed (with respect to mTodayDate). + // + // Our message items cache the formatted dates (as formatting them + // on the fly would be too expensive). We also cache the labels of the groups which often display dates. + // When the date changes we would need to fix all these strings. + // + // A dedicated algorithm to refresh the labels of the items would be either too complex + // or would block on large trees. Fixing the labels of the groups is also quite hard... + // + // So to keep the things simple we just reload the view. - if ( !mViewItemJobs.isEmpty() ) - return; // not now + if ( !mStorageModel ) + return; // nothing to do - if ( mTodayDate == QDate::currentDate() ) - return; // date not changed + if ( mLoading ) + return; // not now - // date changed, reload the view (and try to preserve the current selection) - q->setStorageModel( mStorageModel, PreSelectLastSelected ); + if ( !mViewItemJobs.isEmpty() ) + return; // not now + + if ( mTodayDate == QDate::currentDate() ) + return; // date not changed + + // date changed, reload the view (and try to preserve the current selection) + q->setStorageModel( mStorageModel, PreSelectLastSelected ); } void Model::setPreSelectionMode( PreSelectionMode preSelect ) { - d->mPreSelectionMode = preSelect; - d->mLastSelectedMessageInFolder = 0; + d->mPreSelectionMode = preSelect; + d->mLastSelectedMessageInFolder = 0; } // @@ -918,575 +918,575 @@ void ModelPrivate::clearUnassignedMessageLists() { - // This is a bit tricky... - // The three unassigned message lists contain messages that have been created - // but not yet attached to the view. There may be two major cases for a message: - // - it has no parent -> it must be deleted and it will delete its children too - // - it has a parent -> it must NOT be deleted since it will be deleted by its parent. - - // Sometimes the things get a little complicated since in Pass2 and Pass3 - // we have transitional states in that the MessageItem object can be in two of these lists. - - // WARNING: This function does NOT fixup mNewestItem and mOldestItem. If one of these - // two messages is in the lists below, it's deleted and the member becomes a dangling pointer. - // The caller must ensure that both mNewestItem and mOldestItem are set to 0 - // and this is enforced in the assert below to avoid errors. This basically means - // that this function should be called only when the storage model changes or - // when the model is destroyed. - Q_ASSERT( ( mOldestItem == 0 ) && ( mNewestItem == 0 ) ); - - QList< MessageItem * >::ConstIterator it; - - if ( !mUnassignedMessageListForPass2.isEmpty() ) - { - // We're actually in Pass1* or Pass2: everything is mUnassignedMessageListForPass2 - // Something may *also* be in mUnassignedMessageListForPass3 and mUnassignedMessageListForPass4 - // but that are duplicates for sure. - - // We can't just sweep the list and delete parentless items since each delete - // could kill children which are somewhere AFTER in the list: accessing the children - // would then lead to a SIGSEGV. We first sweep the list gathering parentless - // items and *then* delete them without accessing the parented ones. + // This is a bit tricky... + // The three unassigned message lists contain messages that have been created + // but not yet attached to the view. There may be two major cases for a message: + // - it has no parent -> it must be deleted and it will delete its children too + // - it has a parent -> it must NOT be deleted since it will be deleted by its parent. + + // Sometimes the things get a little complicated since in Pass2 and Pass3 + // we have transitional states in that the MessageItem object can be in two of these lists. + + // WARNING: This function does NOT fixup mNewestItem and mOldestItem. If one of these + // two messages is in the lists below, it's deleted and the member becomes a dangling pointer. + // The caller must ensure that both mNewestItem and mOldestItem are set to 0 + // and this is enforced in the assert below to avoid errors. This basically means + // that this function should be called only when the storage model changes or + // when the model is destroyed. + Q_ASSERT( ( mOldestItem == 0 ) && ( mNewestItem == 0 ) ); + + QList< MessageItem * >::ConstIterator it; + + if ( !mUnassignedMessageListForPass2.isEmpty() ) + { + // We're actually in Pass1* or Pass2: everything is mUnassignedMessageListForPass2 + // Something may *also* be in mUnassignedMessageListForPass3 and mUnassignedMessageListForPass4 + // but that are duplicates for sure. + + // We can't just sweep the list and delete parentless items since each delete + // could kill children which are somewhere AFTER in the list: accessing the children + // would then lead to a SIGSEGV. We first sweep the list gathering parentless + // items and *then* delete them without accessing the parented ones. - QList< MessageItem * > parentless; - QList< MessageItem * >::ConstIterator end( mUnassignedMessageListForPass2.constEnd() ); + QList< MessageItem * > parentless; + QList< MessageItem * >::ConstIterator end( mUnassignedMessageListForPass2.constEnd() ); - for ( it = mUnassignedMessageListForPass2.constBegin(); - it != end; ++it ) - { - if( !( *it )->parent() ) - parentless.append( *it ); + for ( it = mUnassignedMessageListForPass2.constBegin(); + it != end; ++it ) + { + if( !( *it )->parent() ) + parentless.append( *it ); + } + + end = parentless.constEnd(); + for ( it = parentless.constBegin(); it != end; ++it ) + delete *it; + + mUnassignedMessageListForPass2.clear(); + // Any message these list contain was also in mUnassignedMessageListForPass2 + mUnassignedMessageListForPass3.clear(); + mUnassignedMessageListForPass4.clear(); + return; } - end = parentless.constEnd(); - for ( it = parentless.constBegin(); it != end; ++it ) - delete *it; + // mUnassignedMessageListForPass2 is empty - mUnassignedMessageListForPass2.clear(); - // Any message these list contain was also in mUnassignedMessageListForPass2 - mUnassignedMessageListForPass3.clear(); - mUnassignedMessageListForPass4.clear(); - return; - } + if ( !mUnassignedMessageListForPass3.isEmpty() ) + { + // We're actually at the very end of Pass2 or inside Pass3 + // Pass2 pushes stuff in mUnassignedMessageListForPass3 *or* mUnassignedMessageListForPass4 + // Pass3 pushes stuff from mUnassignedMessageListForPass3 to mUnassignedMessageListForPass4 + // So if we're in Pass2 then the two lists contain distinct messages but if we're in Pass3 + // then the two lists may contain the same messages. - // mUnassignedMessageListForPass2 is empty + if ( !mUnassignedMessageListForPass4.isEmpty() ) + { + // We're actually in Pass3: the messiest one. - if ( !mUnassignedMessageListForPass3.isEmpty() ) - { - // We're actually at the very end of Pass2 or inside Pass3 - // Pass2 pushes stuff in mUnassignedMessageListForPass3 *or* mUnassignedMessageListForPass4 - // Pass3 pushes stuff from mUnassignedMessageListForPass3 to mUnassignedMessageListForPass4 - // So if we're in Pass2 then the two lists contain distinct messages but if we're in Pass3 - // then the two lists may contain the same messages. + QHash< MessageItem *, MessageItem * > itemsToDelete; + QList< MessageItem * >::ConstIterator end( mUnassignedMessageListForPass3.constEnd() ); - if ( !mUnassignedMessageListForPass4.isEmpty() ) - { - // We're actually in Pass3: the messiest one. + for ( it = mUnassignedMessageListForPass3.constBegin(); it != end; ++it ) + { + if( !( *it )->parent() ) + itemsToDelete.insert( *it, *it ); + } + end = mUnassignedMessageListForPass4.constEnd(); + for ( it = mUnassignedMessageListForPass4.constBegin(); it != end; ++it ) + { + if( !( *it )->parent() ) + itemsToDelete.insert( *it, *it ); + } + QHash< MessageItem *, MessageItem * >::ConstIterator end3 = itemsToDelete.constEnd(); + for ( QHash< MessageItem *, MessageItem * >::ConstIterator it3 = itemsToDelete.constBegin(); it3 != end3; ++it3 ) + delete ( *it3 ); + + mUnassignedMessageListForPass3.clear(); + mUnassignedMessageListForPass4.clear(); + return; + } - QHash< MessageItem *, MessageItem * > itemsToDelete; - QList< MessageItem * >::ConstIterator end( mUnassignedMessageListForPass3.constEnd() ); + // mUnassignedMessageListForPass4 is empty so we must be at the end of a very special kind of Pass2 + // We have the same problem as in mUnassignedMessageListForPass2. + QList< MessageItem * > parentless; + QList< MessageItem * >::ConstIterator end = mUnassignedMessageListForPass3.constEnd(); + for ( it = mUnassignedMessageListForPass3.constBegin(); it != end; ++it ) + { + if( !( *it )->parent() ) + parentless.append( *it ); + } + end = parentless.constEnd(); + for ( it = parentless.constBegin(); it != end; ++it ) + delete *it; - for ( it = mUnassignedMessageListForPass3.constBegin(); it != end; ++it ) - { - if( !( *it )->parent() ) - itemsToDelete.insert( *it, *it ); - } - end = mUnassignedMessageListForPass4.constEnd(); - for ( it = mUnassignedMessageListForPass4.constBegin(); it != end; ++it ) - { - if( !( *it )->parent() ) - itemsToDelete.insert( *it, *it ); - } - QHash< MessageItem *, MessageItem * >::ConstIterator end3 = itemsToDelete.constEnd(); - for ( QHash< MessageItem *, MessageItem * >::ConstIterator it3 = itemsToDelete.constBegin(); it3 != end3; ++it3 ) - delete ( *it3 ); - - mUnassignedMessageListForPass3.clear(); - mUnassignedMessageListForPass4.clear(); - return; - } - - // mUnassignedMessageListForPass4 is empty so we must be at the end of a very special kind of Pass2 - // We have the same problem as in mUnassignedMessageListForPass2. - QList< MessageItem * > parentless; - QList< MessageItem * >::ConstIterator end = mUnassignedMessageListForPass3.constEnd(); - for ( it = mUnassignedMessageListForPass3.constBegin(); it != end; ++it ) - { - if( !( *it )->parent() ) - parentless.append( *it ); - } - end = parentless.constEnd(); - for ( it = parentless.constBegin(); it != end; ++it ) - delete *it; + mUnassignedMessageListForPass3.clear(); + return; + } - mUnassignedMessageListForPass3.clear(); - return; - } + // mUnassignedMessageListForPass3 is empty + if ( !mUnassignedMessageListForPass4.isEmpty() ) + { + // we're in Pass4.. this is easy. - // mUnassignedMessageListForPass3 is empty - if ( !mUnassignedMessageListForPass4.isEmpty() ) - { - // we're in Pass4.. this is easy. - - // We have the same problem as in mUnassignedMessageListForPass2. - QList< MessageItem * > parentless; - QList< MessageItem * >::ConstIterator end = mUnassignedMessageListForPass4.constEnd(); - for ( it = mUnassignedMessageListForPass4.constBegin(); it != end; ++it ) - { - if( !( *it )->parent() ) - parentless.append( *it ); - } - end = parentless.constEnd(); - for ( it = parentless.constBegin(); it != end; ++it ) - delete *it; + // We have the same problem as in mUnassignedMessageListForPass2. + QList< MessageItem * > parentless; + QList< MessageItem * >::ConstIterator end = mUnassignedMessageListForPass4.constEnd(); + for ( it = mUnassignedMessageListForPass4.constBegin(); it != end; ++it ) + { + if( !( *it )->parent() ) + parentless.append( *it ); + } + end = parentless.constEnd(); + for ( it = parentless.constBegin(); it != end; ++it ) + delete *it; - mUnassignedMessageListForPass4.clear(); - return; - } + mUnassignedMessageListForPass4.clear(); + return; + } } void ModelPrivate::clearThreadingCacheMessageSubjectMD5ToMessageItem() { - qDeleteAll( mThreadingCacheMessageSubjectMD5ToMessageItem ); - mThreadingCacheMessageSubjectMD5ToMessageItem.clear(); + qDeleteAll( mThreadingCacheMessageSubjectMD5ToMessageItem ); + mThreadingCacheMessageSubjectMD5ToMessageItem.clear(); } void ModelPrivate::clearOrphanChildrenHash() { - QHash< MessageItem *, MessageItem * >::ConstIterator end( mOrphanChildrenHash.constEnd() ); - for ( QHash< MessageItem *, MessageItem * >::ConstIterator it = mOrphanChildrenHash.constBegin(); - it != end; ++it ) - { - //Q_ASSERT( !( *it )->parent() ); <-- this assert can actually fail for items that get a temporary parent assigned (to preserve the selection). - delete ( *it ); - } - mOrphanChildrenHash.clear(); + QHash< MessageItem *, MessageItem * >::ConstIterator end( mOrphanChildrenHash.constEnd() ); + for ( QHash< MessageItem *, MessageItem * >::ConstIterator it = mOrphanChildrenHash.constBegin(); + it != end; ++it ) + { + //Q_ASSERT( !( *it )->parent() ); <-- this assert can actually fail for items that get a temporary parent assigned (to preserve the selection). + delete ( *it ); + } + mOrphanChildrenHash.clear(); } void ModelPrivate::clearJobList() { - if ( mViewItemJobs.isEmpty() ) - return; + if ( mViewItemJobs.isEmpty() ) + return; + + if ( mInLengthyJobBatch ) + { + mInLengthyJobBatch = false; + mView->modelJobBatchTerminated(); + } - if ( mInLengthyJobBatch ) - { - mInLengthyJobBatch = false; - mView->modelJobBatchTerminated(); - } - - QList< ViewItemJob * >::ConstIterator end = mViewItemJobs.constEnd(); - for( QList< ViewItemJob * >::ConstIterator it = mViewItemJobs.constBegin(); - it != end; ++it ) - delete ( *it ); - mViewItemJobs.clear(); + QList< ViewItemJob * >::ConstIterator end = mViewItemJobs.constEnd(); + for( QList< ViewItemJob * >::ConstIterator it = mViewItemJobs.constBegin(); + it != end; ++it ) + delete ( *it ); + mViewItemJobs.clear(); - mModelForItemFunctions = q; // make sure it's true, as there remains no job with disconnected UI + mModelForItemFunctions = q; // make sure it's true, as there remains no job with disconnected UI } void ModelPrivate::attachGroup( GroupHeaderItem *ghi ) { - if ( ghi->parent() ) - { - if ( - ( ( ghi )->childItemCount() > 0 ) && // has children - ( ghi )->isViewable() && // is actually attached to the viewable root - mModelForItemFunctions && // the UI is not disconnected - mView->isExpanded( q->index( ghi, 0 ) ) // is actually expanded - ) - saveExpandedStateOfSubtree( ghi ); - - // FIXME: This *WILL* break selection and current index... :/ - - ghi->parent()->takeChildItem( mModelForItemFunctions, ghi ); - } - - ghi->setParent( mRootItem ); - - // I'm using a macro since it does really improve readability. - // I'm NOT using a helper function since gcc will refuse to inline some of - // the calls because they make this function grow too much. + if ( ghi->parent() ) + { + if ( + ( ( ghi )->childItemCount() > 0 ) && // has children + ( ghi )->isViewable() && // is actually attached to the viewable root + mModelForItemFunctions && // the UI is not disconnected + mView->isExpanded( q->index( ghi, 0 ) ) // is actually expanded + ) + saveExpandedStateOfSubtree( ghi ); + + // FIXME: This *WILL* break selection and current index... :/ + + ghi->parent()->takeChildItem( mModelForItemFunctions, ghi ); + } + + ghi->setParent( mRootItem ); + + // I'm using a macro since it does really improve readability. + // I'm NOT using a helper function since gcc will refuse to inline some of + // the calls because they make this function grow too much. #define INSERT_GROUP_WITH_COMPARATOR( _ItemComparator ) \ - switch( mSortOrder->groupSortDirection() ) \ - { \ - case SortOrder::Ascending: \ - mRootItem->d_ptr->insertChildItem< _ItemComparator, true >( mModelForItemFunctions, ghi ); \ - break; \ - case SortOrder::Descending: \ - mRootItem->d_ptr->insertChildItem< _ItemComparator, false >( mModelForItemFunctions, ghi ); \ - break; \ - default: /* should never happen... */ \ - mRootItem->appendChildItem( mModelForItemFunctions, ghi ); \ - break; \ - } + switch( mSortOrder->groupSortDirection() ) \ + { \ + case SortOrder::Ascending: \ + mRootItem->d_ptr->insertChildItem< _ItemComparator, true >( mModelForItemFunctions, ghi ); \ + break; \ + case SortOrder::Descending: \ + mRootItem->d_ptr->insertChildItem< _ItemComparator, false >( mModelForItemFunctions, ghi ); \ + break; \ + default: /* should never happen... */ \ + mRootItem->appendChildItem( mModelForItemFunctions, ghi ); \ + break; \ +} - switch( mSortOrder->groupSorting() ) - { + switch( mSortOrder->groupSorting() ) + { case SortOrder::SortGroupsByDateTime: - INSERT_GROUP_WITH_COMPARATOR( ItemDateComparator ) - break; + INSERT_GROUP_WITH_COMPARATOR( ItemDateComparator ) + break; case SortOrder::SortGroupsByDateTimeOfMostRecent: - INSERT_GROUP_WITH_COMPARATOR( ItemMaxDateComparator ) - break; + INSERT_GROUP_WITH_COMPARATOR( ItemMaxDateComparator ) + break; case SortOrder::SortGroupsBySenderOrReceiver: - INSERT_GROUP_WITH_COMPARATOR( ItemSenderOrReceiverComparator ) - break; + INSERT_GROUP_WITH_COMPARATOR( ItemSenderOrReceiverComparator ) + break; case SortOrder::SortGroupsBySender: - INSERT_GROUP_WITH_COMPARATOR( ItemSenderComparator ) - break; + INSERT_GROUP_WITH_COMPARATOR( ItemSenderComparator ) + break; case SortOrder::SortGroupsByReceiver: - INSERT_GROUP_WITH_COMPARATOR( ItemReceiverComparator ) - break; + INSERT_GROUP_WITH_COMPARATOR( ItemReceiverComparator ) + break; case SortOrder::NoGroupSorting: - mRootItem->appendChildItem( mModelForItemFunctions, ghi ); - break; + mRootItem->appendChildItem( mModelForItemFunctions, ghi ); + break; default: // should never happen - mRootItem->appendChildItem( mModelForItemFunctions, ghi ); - break; - } - - if ( ghi->initialExpandStatus() == Item::ExpandNeeded ) // this actually is a "non viewable expanded state" - if ( ghi->childItemCount() > 0 ) - if ( mModelForItemFunctions ) // the UI is not disconnected - syncExpandedStateOfSubtree( ghi ); - - // A group header is always viewable, when attached: apply the filter, if we have it. - if ( mFilter ) - { - Q_ASSERT( mModelForItemFunctions ); // UI must be NOT disconnected - // apply the filter to subtree - applyFilterToSubtree( ghi, QModelIndex() ); - } + mRootItem->appendChildItem( mModelForItemFunctions, ghi ); + break; + } + + if ( ghi->initialExpandStatus() == Item::ExpandNeeded ) // this actually is a "non viewable expanded state" + if ( ghi->childItemCount() > 0 ) + if ( mModelForItemFunctions ) // the UI is not disconnected + syncExpandedStateOfSubtree( ghi ); + + // A group header is always viewable, when attached: apply the filter, if we have it. + if ( mFilter ) + { + Q_ASSERT( mModelForItemFunctions ); // UI must be NOT disconnected + // apply the filter to subtree + applyFilterToSubtree( ghi, QModelIndex() ); + } } void ModelPrivate::saveExpandedStateOfSubtree( Item *root ) { - Q_ASSERT( mModelForItemFunctions ); // UI must be NOT disconnected here - Q_ASSERT( root ); + Q_ASSERT( mModelForItemFunctions ); // UI must be NOT disconnected here + Q_ASSERT( root ); - root->setInitialExpandStatus( Item::ExpandNeeded ); + root->setInitialExpandStatus( Item::ExpandNeeded ); - QList< Item * > * children = root->childItems(); - if ( !children ) - return; - QList< Item * >::ConstIterator end( children->constEnd() ); - for( QList< Item * >::ConstIterator it = children->constBegin(); it != end; ++it ) - { - if ( - ( ( *it )->childItemCount() > 0 ) && // has children - ( *it )->isViewable() && // is actually attached to the viewable root - mView->isExpanded( q->index( *it, 0 ) ) // is actually expanded - ) - saveExpandedStateOfSubtree( *it ); - } + QList< Item * > * children = root->childItems(); + if ( !children ) + return; + QList< Item * >::ConstIterator end( children->constEnd() ); + for( QList< Item * >::ConstIterator it = children->constBegin(); it != end; ++it ) + { + if ( + ( ( *it )->childItemCount() > 0 ) && // has children + ( *it )->isViewable() && // is actually attached to the viewable root + mView->isExpanded( q->index( *it, 0 ) ) // is actually expanded + ) + saveExpandedStateOfSubtree( *it ); + } } void ModelPrivate::syncExpandedStateOfSubtree( Item *root ) { - Q_ASSERT( mModelForItemFunctions ); // UI must be NOT disconnected here + Q_ASSERT( mModelForItemFunctions ); // UI must be NOT disconnected here - // WE ASSUME that: - // - the item is viewable - // - its initialExpandStatus() is Item::ExpandNeeded - // - it has at least one children (well.. this is not a strict requirement, but it's a waste of resources to expand items that don't have children) + // WE ASSUME that: + // - the item is viewable + // - its initialExpandStatus() is Item::ExpandNeeded + // - it has at least one children (well.. this is not a strict requirement, but it's a waste of resources to expand items that don't have children) - QModelIndex idx = q->index( root, 0 ); + QModelIndex idx = q->index( root, 0 ); - //if ( !mView->isExpanded( idx ) ) // this is O(logN!) in Qt.... very ugly... but it should never happen here - mView->expand( idx ); // sync the real state in the view - root->setInitialExpandStatus( Item::ExpandExecuted ); + //if ( !mView->isExpanded( idx ) ) // this is O(logN!) in Qt.... very ugly... but it should never happen here + mView->expand( idx ); // sync the real state in the view + root->setInitialExpandStatus( Item::ExpandExecuted ); - QList< Item * > * children = root->childItems(); - if ( !children ) - return; + QList< Item * > * children = root->childItems(); + if ( !children ) + return; - QList< Item * >::ConstIterator end( children->constEnd() ); - for( QList< Item * >::ConstIterator it = children->constBegin(); it != end; ++it ) - { - if ( ( *it )->initialExpandStatus() == Item::ExpandNeeded ) + QList< Item * >::ConstIterator end( children->constEnd() ); + for( QList< Item * >::ConstIterator it = children->constBegin(); it != end; ++it ) { - if ( ( *it )->childItemCount() > 0 ) - syncExpandedStateOfSubtree( *it ); + if ( ( *it )->initialExpandStatus() == Item::ExpandNeeded ) + { + if ( ( *it )->childItemCount() > 0 ) + syncExpandedStateOfSubtree( *it ); + } } - } } void ModelPrivate::attachMessageToGroupHeader( MessageItem *mi ) { - QString groupLabel; - time_t date; + QString groupLabel; + time_t date; - // compute the group header label and the date - switch( mAggregation->grouping() ) - { + // compute the group header label and the date + switch( mAggregation->grouping() ) + { case Aggregation::GroupByDate: case Aggregation::GroupByDateRange: { - if ( mAggregation->threadLeader() == Aggregation::MostRecentMessage ) - { - date = mi->maxDate(); - } else - { - date = mi->date(); - } - - QDateTime dt; - dt.setTime_t( date ); - QDate dDate = dt.date(); - const KCalendarSystem *calendar = KGlobal::locale()->calendar(); - int daysAgo = -1; - if ( calendar->isValid( dDate ) && calendar->isValid( mTodayDate ) ) { - daysAgo = dDate.daysTo( mTodayDate ); - } - - if ( ( daysAgo < 0 ) || // In the future - ( static_cast< uint >( date ) == static_cast< uint >( -1 ) ) ) // Invalid - { - groupLabel = mCachedUnknownLabel; - } else if( daysAgo == 0 ) // Today - { - groupLabel = mCachedTodayLabel; - } else if ( daysAgo == 1 ) // Yesterday - { - groupLabel = mCachedYesterdayLabel; - } else if ( daysAgo > 1 && daysAgo < calendar->daysInWeek( mTodayDate ) ) // Within last seven days - { - groupLabel = KGlobal::locale()->calendar()->weekDayName( dDate ); - } else if ( mAggregation->grouping() == Aggregation::GroupByDate ) { // GroupByDate seven days or more ago - groupLabel = KGlobal::locale()->formatDate( dDate, KLocale::ShortDate ); - } else if( ( calendar->month( dDate ) == calendar->month( mTodayDate ) ) && // GroupByDateRange within this month - ( calendar->year( dDate ) == calendar->year( mTodayDate ) ) ) - { - int startOfWeekDaysAgo = ( calendar->daysInWeek( mTodayDate ) + calendar->dayOfWeek( mTodayDate ) - - KGlobal::locale()->weekStartDay() ) % calendar->daysInWeek( mTodayDate ); - int weeksAgo = ( ( daysAgo - startOfWeekDaysAgo ) / calendar->daysInWeek( mTodayDate ) ) + 1; - switch( weeksAgo ) + if ( mAggregation->threadLeader() == Aggregation::MostRecentMessage ) + { + date = mi->maxDate(); + } else + { + date = mi->date(); + } + + QDateTime dt; + dt.setTime_t( date ); + QDate dDate = dt.date(); + const KCalendarSystem *calendar = KGlobal::locale()->calendar(); + int daysAgo = -1; + if ( calendar->isValid( dDate ) && calendar->isValid( mTodayDate ) ) { + daysAgo = dDate.daysTo( mTodayDate ); + } + + if ( ( daysAgo < 0 ) || // In the future + ( static_cast< uint >( date ) == static_cast< uint >( -1 ) ) ) // Invalid { - case 0: // This week - groupLabel = KGlobal::locale()->calendar()->weekDayName( dDate ); - break; - case 1: // 1 week ago - groupLabel = mCachedLastWeekLabel; - break; - case 2: - groupLabel = mCachedTwoWeeksAgoLabel; - break; - case 3: - groupLabel = mCachedThreeWeeksAgoLabel; - break; - case 4: - groupLabel = mCachedFourWeeksAgoLabel; - break; - case 5: - groupLabel = mCachedFiveWeeksAgoLabel; - break; - default: // should never happen groupLabel = mCachedUnknownLabel; + } else if( daysAgo == 0 ) // Today + { + groupLabel = mCachedTodayLabel; + } else if ( daysAgo == 1 ) // Yesterday + { + groupLabel = mCachedYesterdayLabel; + } else if ( daysAgo > 1 && daysAgo < calendar->daysInWeek( mTodayDate ) ) // Within last seven days + { + groupLabel = KGlobal::locale()->calendar()->weekDayName( dDate ); + } else if ( mAggregation->grouping() == Aggregation::GroupByDate ) { // GroupByDate seven days or more ago + groupLabel = KGlobal::locale()->formatDate( dDate, KLocale::ShortDate ); + } else if( ( calendar->month( dDate ) == calendar->month( mTodayDate ) ) && // GroupByDateRange within this month + ( calendar->year( dDate ) == calendar->year( mTodayDate ) ) ) + { + int startOfWeekDaysAgo = ( calendar->daysInWeek( mTodayDate ) + calendar->dayOfWeek( mTodayDate ) - + KGlobal::locale()->weekStartDay() ) % calendar->daysInWeek( mTodayDate ); + int weeksAgo = ( ( daysAgo - startOfWeekDaysAgo ) / calendar->daysInWeek( mTodayDate ) ) + 1; + switch( weeksAgo ) + { + case 0: // This week + groupLabel = KGlobal::locale()->calendar()->weekDayName( dDate ); + break; + case 1: // 1 week ago + groupLabel = mCachedLastWeekLabel; + break; + case 2: + groupLabel = mCachedTwoWeeksAgoLabel; + break; + case 3: + groupLabel = mCachedThreeWeeksAgoLabel; + break; + case 4: + groupLabel = mCachedFourWeeksAgoLabel; + break; + case 5: + groupLabel = mCachedFiveWeeksAgoLabel; + break; + default: // should never happen + groupLabel = mCachedUnknownLabel; + } + } else if ( calendar->year( dDate ) == calendar->year( mTodayDate ) ) { // GroupByDateRange within this year + groupLabel = calendar->monthName( dDate ); + } else { // GroupByDateRange in previous years + groupLabel = i18nc( "Message Aggregation Group Header: Month name and Year number", "%1 %2", calendar->monthName( dDate ), + calendar->formatDate( dDate, KLocale::Year, KLocale::LongNumber ) ); } - } else if ( calendar->year( dDate ) == calendar->year( mTodayDate ) ) { // GroupByDateRange within this year - groupLabel = calendar->monthName( dDate ); - } else { // GroupByDateRange in previous years - groupLabel = i18nc( "Message Aggregation Group Header: Month name and Year number", "%1 %2", calendar->monthName( dDate ), - calendar->formatDate( dDate, KLocale::Year, KLocale::LongNumber ) ); - } - break; + break; } case Aggregation::GroupBySenderOrReceiver: - date = mi->date(); - groupLabel = MessageCore::StringUtil::stripEmailAddr( mi->senderOrReceiver() ); - break; + date = mi->date(); + groupLabel = MessageCore::StringUtil::stripEmailAddr( mi->senderOrReceiver() ); + break; case Aggregation::GroupBySender: - date = mi->date(); - groupLabel = MessageCore::StringUtil::stripEmailAddr( mi->sender() ); - break; + date = mi->date(); + groupLabel = MessageCore::StringUtil::stripEmailAddr( mi->sender() ); + break; case Aggregation::GroupByReceiver: - date = mi->date(); - groupLabel = MessageCore::StringUtil::stripEmailAddr( mi->receiver() ); - break; + date = mi->date(); + groupLabel = MessageCore::StringUtil::stripEmailAddr( mi->receiver() ); + break; case Aggregation::NoGrouping: - // append directly to root - attachMessageToParent( mRootItem, mi ); - return; + // append directly to root + attachMessageToParent( mRootItem, mi ); + return; default: - // should never happen - attachMessageToParent( mRootItem, mi ); - return; - } - - GroupHeaderItem * ghi; - - ghi = mGroupHeaderItemHash.value( groupLabel, 0 ); - if( !ghi ) - { - // not found - - ghi = new GroupHeaderItem( groupLabel ); - ghi->initialSetup( date, mi->size(), mi->sender(), mi->receiver(), mi->useReceiver() ); - - switch( mAggregation->groupExpandPolicy() ) - { - case Aggregation::NeverExpandGroups: - // nothing to do - break; - case Aggregation::AlwaysExpandGroups: - // expand always - ghi->setInitialExpandStatus( Item::ExpandNeeded ); - break; - case Aggregation::ExpandRecentGroups: - // expand only if "close" to today - if ( mViewItemJobStepStartTime > ghi->date() ) + // should never happen + attachMessageToParent( mRootItem, mi ); + return; + } + + GroupHeaderItem * ghi; + + ghi = mGroupHeaderItemHash.value( groupLabel, 0 ); + if( !ghi ) + { + // not found + + ghi = new GroupHeaderItem( groupLabel ); + ghi->initialSetup( date, mi->size(), mi->sender(), mi->receiver(), mi->useReceiver() ); + + switch( mAggregation->groupExpandPolicy() ) { - if ( ( mViewItemJobStepStartTime - ghi->date() ) < ( 3600 * 72 ) ) - ghi->setInitialExpandStatus( Item::ExpandNeeded ); - } else { - if ( ( ghi->date() - mViewItemJobStepStartTime ) < ( 3600 * 72 ) ) - ghi->setInitialExpandStatus( Item::ExpandNeeded ); + case Aggregation::NeverExpandGroups: + // nothing to do + break; + case Aggregation::AlwaysExpandGroups: + // expand always + ghi->setInitialExpandStatus( Item::ExpandNeeded ); + break; + case Aggregation::ExpandRecentGroups: + // expand only if "close" to today + if ( mViewItemJobStepStartTime > ghi->date() ) + { + if ( ( mViewItemJobStepStartTime - ghi->date() ) < ( 3600 * 72 ) ) + ghi->setInitialExpandStatus( Item::ExpandNeeded ); + } else { + if ( ( ghi->date() - mViewItemJobStepStartTime ) < ( 3600 * 72 ) ) + ghi->setInitialExpandStatus( Item::ExpandNeeded ); + } + break; + default: + // b0rken + break; } - break; - default: - // b0rken - break; - } - attachMessageToParent( ghi, mi ); + attachMessageToParent( ghi, mi ); - attachGroup( ghi ); // this will expand the group if required + attachGroup( ghi ); // this will expand the group if required - mGroupHeaderItemHash.insert( groupLabel, ghi ); - } else { - // the group was already there (certainly viewable) + mGroupHeaderItemHash.insert( groupLabel, ghi ); + } else { + // the group was already there (certainly viewable) - // This function may be also called to re-group a message. - // That is, to eventually find a new group for a message that has changed - // its properties (but was already attacched to a group). - // So it may happen that we find out that in fact re-grouping wasn't really - // needed because the message is already in the correct group. - if ( mi->parent() == ghi ) - return; // nothing to be done + // This function may be also called to re-group a message. + // That is, to eventually find a new group for a message that has changed + // its properties (but was already attacched to a group). + // So it may happen that we find out that in fact re-grouping wasn't really + // needed because the message is already in the correct group. + if ( mi->parent() == ghi ) + return; // nothing to be done - attachMessageToParent( ghi, mi ); - } + attachMessageToParent( ghi, mi ); + } } MessageItem * ModelPrivate::findMessageParent( MessageItem * mi ) { - Q_ASSERT( mAggregation->threading() != Aggregation::NoThreading ); // caller must take care of this + Q_ASSERT( mAggregation->threading() != Aggregation::NoThreading ); // caller must take care of this + + // This function attempts to find a thread parent for the item "mi" + // which actually may already have a children subtree. + + // Forged or plain broken message trees are dangerous here. + // For example, a message tree with circular references like + // + // Message mi, Id=1, In-Reply-To=2 + // Message childOfMi, Id=2, In-Reply-To=1 + // + // is perfectly possible and will cause us to find childOfMi + // as parent of mi. This will then create a loop in the message tree + // (which will then no longer be a tree in fact) and cause us to freeze + // once we attempt to climb the parents. We need to take care of that. + + bool bMessageWasThreadable = false; + MessageItem * pParent; + + // First of all try to find a "perfect parent", that is the message for that + // we have the ID in the "In-Reply-To" field. This is actually done by using + // MD5 caches of the message ids because of speed. Collisions are very unlikely. + + QByteArray md5 = mi->inReplyToIdMD5(); + if ( !md5.isEmpty() ) + { + // have an In-Reply-To field MD5 + pParent = mThreadingCacheMessageIdMD5ToMessageItem.value( md5, 0 ); + if(pParent) + { + // Take care of circular references + if ( + ( mi == pParent ) || // self referencing message + ( + ( mi->childItemCount() > 0 ) && // mi already has children, this is fast to determine + pParent->hasAncestor( mi ) // pParent is in the mi's children tree + ) + ) + { + kWarning() << "Circular In-Reply-To reference loop detected in the message tree"; + mi->setThreadingStatus( MessageItem::NonThreadable ); + return 0; // broken message: throw it away + } + mi->setThreadingStatus( MessageItem::PerfectParentFound ); + return pParent; // got a perfect parent for this message + } + + // got no perfect parent + bMessageWasThreadable = true; // but the message was threadable + } + + if ( mAggregation->threading() == Aggregation::PerfectOnly ) + { + mi->setThreadingStatus( bMessageWasThreadable ? MessageItem::ParentMissing : MessageItem::NonThreadable ); + return 0; // we're doing only perfect parent matches + } + + // Try to use the "References" field. In fact we have the MD5 of the + // (n-1)th entry in References. + // + // Original rationale from KMHeaders: + // + // If we don't have a replyToId, or if we have one and the + // corresponding message is not in this folder, as happens + // if you keep your outgoing messages in an OUTBOX, for + // example, try the list of references, because the second + // to last will likely be in this folder. replyToAuxIdMD5 + // contains the second to last one. + + md5 = mi->referencesIdMD5(); + if ( !md5.isEmpty() ) + { + pParent = mThreadingCacheMessageIdMD5ToMessageItem.value( md5, 0 ); + if(pParent) + { + // Take care of circular references + if ( + ( mi == pParent ) || // self referencing message + ( + ( mi->childItemCount() > 0 ) && // mi already has children, this is fast to determine + pParent->hasAncestor( mi ) // pParent is in the mi's children tree + ) + ) + { + kWarning() << "Circular reference loop detected in the message tree"; + mi->setThreadingStatus( MessageItem::NonThreadable ); + return 0; // broken message: throw it away + } + mi->setThreadingStatus( MessageItem::ImperfectParentFound ); + return pParent; // got an imperfect parent for this message + } + + // got no imperfect parent + bMessageWasThreadable = true; // but the message was threadable + } - // This function attempts to find a thread parent for the item "mi" - // which actually may already have a children subtree. + if ( mAggregation->threading() == Aggregation::PerfectAndReferences ) + { + mi->setThreadingStatus( bMessageWasThreadable ? MessageItem::ParentMissing : MessageItem::NonThreadable ); + return 0; // we're doing only perfect parent matches + } - // Forged or plain broken message trees are dangerous here. - // For example, a message tree with circular references like - // - // Message mi, Id=1, In-Reply-To=2 - // Message childOfMi, Id=2, In-Reply-To=1 - // - // is perfectly possible and will cause us to find childOfMi - // as parent of mi. This will then create a loop in the message tree - // (which will then no longer be a tree in fact) and cause us to freeze - // once we attempt to climb the parents. We need to take care of that. - - bool bMessageWasThreadable = false; - MessageItem * pParent; - - // First of all try to find a "perfect parent", that is the message for that - // we have the ID in the "In-Reply-To" field. This is actually done by using - // MD5 caches of the message ids because of speed. Collisions are very unlikely. - - QByteArray md5 = mi->inReplyToIdMD5(); - if ( !md5.isEmpty() ) - { - // have an In-Reply-To field MD5 - pParent = mThreadingCacheMessageIdMD5ToMessageItem.value( md5, 0 ); - if(pParent) - { - // Take care of circular references - if ( - ( mi == pParent ) || // self referencing message - ( - ( mi->childItemCount() > 0 ) && // mi already has children, this is fast to determine - pParent->hasAncestor( mi ) // pParent is in the mi's children tree - ) - ) - { - kWarning() << "Circular In-Reply-To reference loop detected in the message tree"; - mi->setThreadingStatus( MessageItem::NonThreadable ); - return 0; // broken message: throw it away - } - mi->setThreadingStatus( MessageItem::PerfectParentFound ); - return pParent; // got a perfect parent for this message - } - - // got no perfect parent - bMessageWasThreadable = true; // but the message was threadable - } - - if ( mAggregation->threading() == Aggregation::PerfectOnly ) - { - mi->setThreadingStatus( bMessageWasThreadable ? MessageItem::ParentMissing : MessageItem::NonThreadable ); - return 0; // we're doing only perfect parent matches - } - - // Try to use the "References" field. In fact we have the MD5 of the - // (n-1)th entry in References. - // - // Original rationale from KMHeaders: - // - // If we don't have a replyToId, or if we have one and the - // corresponding message is not in this folder, as happens - // if you keep your outgoing messages in an OUTBOX, for - // example, try the list of references, because the second - // to last will likely be in this folder. replyToAuxIdMD5 - // contains the second to last one. - - md5 = mi->referencesIdMD5(); - if ( !md5.isEmpty() ) - { - pParent = mThreadingCacheMessageIdMD5ToMessageItem.value( md5, 0 ); - if(pParent) - { - // Take care of circular references - if ( - ( mi == pParent ) || // self referencing message - ( - ( mi->childItemCount() > 0 ) && // mi already has children, this is fast to determine - pParent->hasAncestor( mi ) // pParent is in the mi's children tree - ) - ) - { - kWarning() << "Circular reference loop detected in the message tree"; - mi->setThreadingStatus( MessageItem::NonThreadable ); - return 0; // broken message: throw it away - } - mi->setThreadingStatus( MessageItem::ImperfectParentFound ); - return pParent; // got an imperfect parent for this message - } - - // got no imperfect parent - bMessageWasThreadable = true; // but the message was threadable - } - - if ( mAggregation->threading() == Aggregation::PerfectAndReferences ) - { - mi->setThreadingStatus( bMessageWasThreadable ? MessageItem::ParentMissing : MessageItem::NonThreadable ); - return 0; // we're doing only perfect parent matches - } - - Q_ASSERT( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ); - - // We are supposed to do subject based threading but we can't do it now. - // This is because the subject based threading *may* be wrong and waste - // time by creating circular references (that we'd need to detect and fix). - // We first try the perfect and references based threading on all the messages - // and then run subject based threading only on the remaining ones. + Q_ASSERT( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ); - mi->setThreadingStatus( ( bMessageWasThreadable || mi->subjectIsPrefixed() ) ? MessageItem::ParentMissing : MessageItem::NonThreadable ); - return 0; + // We are supposed to do subject based threading but we can't do it now. + // This is because the subject based threading *may* be wrong and waste + // time by creating circular references (that we'd need to detect and fix). + // We first try the perfect and references based threading on all the messages + // and then run subject based threading only on the remaining ones. + + mi->setThreadingStatus( ( bMessageWasThreadable || mi->subjectIsPrefixed() ) ? MessageItem::ParentMissing : MessageItem::NonThreadable ); + return 0; } // Subject threading cache stuff @@ -1495,30 +1495,30 @@ // Debug helpers void dump_iterator_and_list( QList< MessageItem * >::Iterator &iter, QList< MessageItem * > *list ) { - kDebug() << "Threading cache part dump" << endl; - if ( iter == list->end() ) - kDebug() << "Iterator pointing to end of the list" << endl; - else - kDebug() << "Iterator pointing to " << *iter << " subject [" << (*iter)->subject() << "] date [" << (*iter)->date() << "]" << endl; - - for ( QList< MessageItem * >::Iterator it = list->begin(); it != list->end(); ++it ) - { - kDebug() << "List element " << *it << " subject [" << (*it)->subject() << "] date [" << (*it)->date() << "]" << endl; - } + kDebug() << "Threading cache part dump" << endl; + if ( iter == list->end() ) + kDebug() << "Iterator pointing to end of the list" << endl; + else + kDebug() << "Iterator pointing to " << *iter << " subject [" << (*iter)->subject() << "] date [" << (*iter)->date() << "]" << endl; + + for ( QList< MessageItem * >::Iterator it = list->begin(); it != list->end(); ++it ) + { + kDebug() << "List element " << *it << " subject [" << (*it)->subject() << "] date [" << (*it)->date() << "]" << endl; + } - kDebug() << "End of threading cache part dump" << endl; + kDebug() << "End of threading cache part dump" << endl; } void dump_list( QList< MessageItem * > *list ) { - kDebug() << "Threading cache part dump" << endl; + kDebug() << "Threading cache part dump" << endl; - for ( QList< MessageItem * >::Iterator it = list->begin(); it != list->end(); ++it ) - { - kDebug() << "List element " << *it << " subject [" << (*it)->subject() << "] date [" << (*it)->date() << "]" << endl; - } + for ( QList< MessageItem * >::Iterator it = list->begin(); it != list->end(); ++it ) + { + kDebug() << "List element " << *it << " subject [" << (*it)->subject() << "] date [" << (*it)->date() << "]" << endl; + } - kDebug() << "End of threading cache part dump" << endl; + kDebug() << "End of threading cache part dump" << endl; } #endif // debug helpers @@ -1526,169 +1526,169 @@ class MessageLessThanByDate { public: - inline bool operator()( const MessageItem * mi1, const MessageItem * mi2 ) const - { - if ( mi1->date() < mi2->date() ) // likely - return true; - if ( mi1->date() > mi2->date() ) // likely - return false; - // dates are equal, compare by pointer - return mi1 < mi2; - } + inline bool operator()( const MessageItem * mi1, const MessageItem * mi2 ) const + { + if ( mi1->date() < mi2->date() ) // likely + return true; + if ( mi1->date() > mi2->date() ) // likely + return false; + // dates are equal, compare by pointer + return mi1 < mi2; + } }; void ModelPrivate::addMessageToSubjectBasedThreadingCache( MessageItem * mi ) { - // Messages in this cache are sorted by date, and if dates are equal then they are sorted by pointer value. - // Sorting by date is used to optimize the parent lookup in guessMessageParent() below. + // Messages in this cache are sorted by date, and if dates are equal then they are sorted by pointer value. + // Sorting by date is used to optimize the parent lookup in guessMessageParent() below. - // WARNING: If the message date changes for some reason (like in the "update" step) - // then the cache may become unsorted. For this reason the message about to - // be changed must be first removed from the cache and then reinserted. - - // Lookup the list of messages with the same stripped subject - QList< MessageItem * > * messagesWithTheSameStrippedSubject = - mThreadingCacheMessageSubjectMD5ToMessageItem.value( mi->strippedSubjectMD5(), 0 ); - - if ( !messagesWithTheSameStrippedSubject ) - { - // Not there yet: create it and append. - messagesWithTheSameStrippedSubject = new QList< MessageItem * >(); - mThreadingCacheMessageSubjectMD5ToMessageItem.insert( mi->strippedSubjectMD5(), messagesWithTheSameStrippedSubject ); - messagesWithTheSameStrippedSubject->append( mi ); - return; - } - - // Found: assert that we have no duplicates in the cache. - Q_ASSERT( !messagesWithTheSameStrippedSubject->contains( mi ) ); - - // Ordered insert: first by date then by pointer value. - QList< MessageItem * >::Iterator it = qLowerBound( messagesWithTheSameStrippedSubject->begin(), messagesWithTheSameStrippedSubject->end(), mi, MessageLessThanByDate() ); - messagesWithTheSameStrippedSubject->insert( it, mi ); -} - -void ModelPrivate::removeMessageFromSubjectBasedThreadingCache( MessageItem * mi ) -{ - // We assume that the caller knows what he is doing and the message is actually in the cache. - // If the message isn't in the cache then we should be called at all. - // - // The game is called "performance" - - // Grab the list of all the messages with the same stripped subject (all potential parents) - QList< MessageItem * > * messagesWithTheSameStrippedSubject = mThreadingCacheMessageSubjectMD5ToMessageItem.value( mi->strippedSubjectMD5(), 0 ); - - // We assume that the message is there so the list must be non null. - Q_ASSERT( messagesWithTheSameStrippedSubject ); - - // The cache *MUST* be ordered first by date then by pointer value - QList< MessageItem * >::Iterator it = qLowerBound( messagesWithTheSameStrippedSubject->begin(), messagesWithTheSameStrippedSubject->end(), mi, MessageLessThanByDate() ); - - // The binary based search must have found a message - Q_ASSERT( it != messagesWithTheSameStrippedSubject->end() ); - - // and it must have found exactly the message requested - Q_ASSERT( *it == mi ); - - // Kill it - messagesWithTheSameStrippedSubject->erase( it ); - - // And kill the list if it was the last one - if ( messagesWithTheSameStrippedSubject->isEmpty() ) - { - mThreadingCacheMessageSubjectMD5ToMessageItem.remove( mi->strippedSubjectMD5() ); - delete messagesWithTheSameStrippedSubject; - } -} + // WARNING: If the message date changes for some reason (like in the "update" step) + // then the cache may become unsorted. For this reason the message about to + // be changed must be first removed from the cache and then reinserted. -MessageItem * ModelPrivate::guessMessageParent( MessageItem * mi ) -{ - // This function implements subject based threading - // It attempts to guess a thread parent for the item "mi" - // which actually may already have a children subtree. - - // We have all the problems of findMessageParent() plus the fact that - // we're actually guessing (and often we may be *wrong*). - - Q_ASSERT( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ); // caller must take care of this - Q_ASSERT( mi->subjectIsPrefixed() ); // caller must take care of this - Q_ASSERT( mi->threadingStatus() == MessageItem::ParentMissing ); - - - // Do subject based threading - const QByteArray md5 = mi->strippedSubjectMD5(); - if ( !md5.isEmpty() ) - { + // Lookup the list of messages with the same stripped subject QList< MessageItem * > * messagesWithTheSameStrippedSubject = - mThreadingCacheMessageSubjectMD5ToMessageItem.value( md5, 0 ); + mThreadingCacheMessageSubjectMD5ToMessageItem.value( mi->strippedSubjectMD5(), 0 ); - if ( messagesWithTheSameStrippedSubject ) + if ( !messagesWithTheSameStrippedSubject ) { - Q_ASSERT( messagesWithTheSameStrippedSubject->count() > 0 ); + // Not there yet: create it and append. + messagesWithTheSameStrippedSubject = new QList< MessageItem * >(); + mThreadingCacheMessageSubjectMD5ToMessageItem.insert( mi->strippedSubjectMD5(), messagesWithTheSameStrippedSubject ); + messagesWithTheSameStrippedSubject->append( mi ); + return; + } - // Need to find the message with the maximum date lower than the one of this message + // Found: assert that we have no duplicates in the cache. + Q_ASSERT( !messagesWithTheSameStrippedSubject->contains( mi ) ); - time_t maxTime = (time_t)0; - MessageItem * pParent = 0; + // Ordered insert: first by date then by pointer value. + QList< MessageItem * >::Iterator it = qLowerBound( messagesWithTheSameStrippedSubject->begin(), messagesWithTheSameStrippedSubject->end(), mi, MessageLessThanByDate() ); + messagesWithTheSameStrippedSubject->insert( it, mi ); +} - // Here'we re really guessing so circular references are possible - // even on perfectly valid trees. This is why we don't consider it - // an error but just continue searching. +void ModelPrivate::removeMessageFromSubjectBasedThreadingCache( MessageItem * mi ) +{ + // We assume that the caller knows what he is doing and the message is actually in the cache. + // If the message isn't in the cache then we should be called at all. + // + // The game is called "performance" - // FIXME: This might be speed up with an initial binary search (?) - // ANSWER: No. We can't rely on date order (as it can be updated on the fly...) - QList< MessageItem * >::ConstIterator end( messagesWithTheSameStrippedSubject->constEnd() ); + // Grab the list of all the messages with the same stripped subject (all potential parents) + QList< MessageItem * > * messagesWithTheSameStrippedSubject = mThreadingCacheMessageSubjectMD5ToMessageItem.value( mi->strippedSubjectMD5(), 0 ); - for ( QList< MessageItem * >::ConstIterator it = messagesWithTheSameStrippedSubject->constBegin(); it != end; ++it ) - { - int delta = mi->date() - ( *it )->date(); + // We assume that the message is there so the list must be non null. + Q_ASSERT( messagesWithTheSameStrippedSubject ); - // We don't take into account messages with a delta smaller than 120. - // Assuming that our date() values are correct (that is, they take into - // account timezones etc..) then one usually needs more than 120 seconds - // to answer to a message. Better safe than sorry. + // The cache *MUST* be ordered first by date then by pointer value + QList< MessageItem * >::Iterator it = qLowerBound( messagesWithTheSameStrippedSubject->begin(), messagesWithTheSameStrippedSubject->end(), mi, MessageLessThanByDate() ); - // This check also includes negative deltas so messages later than mi aren't considered + // The binary based search must have found a message + Q_ASSERT( it != messagesWithTheSameStrippedSubject->end() ); - if ( delta < 120 ) - break; // The list is ordered by date (ascending) so we can stop searching here + // and it must have found exactly the message requested + Q_ASSERT( *it == mi ); - // About the "magic" 3628899 value here comes a Till's comment from the original KMHeaders: - // - // "Parents more than six weeks older than the message are not accepted. The reasoning being - // that if a new message with the same subject turns up after such a long time, the chances - // that it is still part of the same thread are slim. The value of six weeks is chosen as a - // result of a poll conducted on kde-devel, so it's probably bogus. :)" + // Kill it + messagesWithTheSameStrippedSubject->erase( it ); + + // And kill the list if it was the last one + if ( messagesWithTheSameStrippedSubject->isEmpty() ) + { + mThreadingCacheMessageSubjectMD5ToMessageItem.remove( mi->strippedSubjectMD5() ); + delete messagesWithTheSameStrippedSubject; + } +} + +MessageItem * ModelPrivate::guessMessageParent( MessageItem * mi ) +{ + // This function implements subject based threading + // It attempts to guess a thread parent for the item "mi" + // which actually may already have a children subtree. + + // We have all the problems of findMessageParent() plus the fact that + // we're actually guessing (and often we may be *wrong*). + + Q_ASSERT( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ); // caller must take care of this + Q_ASSERT( mi->subjectIsPrefixed() ); // caller must take care of this + Q_ASSERT( mi->threadingStatus() == MessageItem::ParentMissing ); + + + // Do subject based threading + const QByteArray md5 = mi->strippedSubjectMD5(); + if ( !md5.isEmpty() ) + { + QList< MessageItem * > * messagesWithTheSameStrippedSubject = + mThreadingCacheMessageSubjectMD5ToMessageItem.value( md5, 0 ); - if ( delta < 3628899 ) + if ( messagesWithTheSameStrippedSubject ) { - // Compute the closest. - if ( ( maxTime < ( *it )->date() ) ) - { - // This algorithm *can* be (and often is) wrong. - // Take care of circular threading which is really possible at this level. - // If mi contains (*it) inside its children subtree then we have - // found such a circular threading problem. + Q_ASSERT( messagesWithTheSameStrippedSubject->count() > 0 ); - // Note that here we can't have *it == mi because of the delta >= 120 check above. + // Need to find the message with the maximum date lower than the one of this message - if ( ( mi->childItemCount() == 0 ) || !( *it )->hasAncestor( mi ) ) + time_t maxTime = (time_t)0; + MessageItem * pParent = 0; + + // Here'we re really guessing so circular references are possible + // even on perfectly valid trees. This is why we don't consider it + // an error but just continue searching. + + // FIXME: This might be speed up with an initial binary search (?) + // ANSWER: No. We can't rely on date order (as it can be updated on the fly...) + QList< MessageItem * >::ConstIterator end( messagesWithTheSameStrippedSubject->constEnd() ); + + for ( QList< MessageItem * >::ConstIterator it = messagesWithTheSameStrippedSubject->constBegin(); it != end; ++it ) { - maxTime = ( *it )->date(); - pParent = ( *it ); + int delta = mi->date() - ( *it )->date(); + + // We don't take into account messages with a delta smaller than 120. + // Assuming that our date() values are correct (that is, they take into + // account timezones etc..) then one usually needs more than 120 seconds + // to answer to a message. Better safe than sorry. + + // This check also includes negative deltas so messages later than mi aren't considered + + if ( delta < 120 ) + break; // The list is ordered by date (ascending) so we can stop searching here + + // About the "magic" 3628899 value here comes a Till's comment from the original KMHeaders: + // + // "Parents more than six weeks older than the message are not accepted. The reasoning being + // that if a new message with the same subject turns up after such a long time, the chances + // that it is still part of the same thread are slim. The value of six weeks is chosen as a + // result of a poll conducted on kde-devel, so it's probably bogus. :)" + + if ( delta < 3628899 ) + { + // Compute the closest. + if ( ( maxTime < ( *it )->date() ) ) + { + // This algorithm *can* be (and often is) wrong. + // Take care of circular threading which is really possible at this level. + // If mi contains (*it) inside its children subtree then we have + // found such a circular threading problem. + + // Note that here we can't have *it == mi because of the delta >= 120 check above. + + if ( ( mi->childItemCount() == 0 ) || !( *it )->hasAncestor( mi ) ) + { + maxTime = ( *it )->date(); + pParent = ( *it ); + } + } + } } - } - } - } - if ( pParent ) - { - mi->setThreadingStatus( MessageItem::ImperfectParentFound ); - return pParent; // got an imperfect parent for this message - } + if ( pParent ) + { + mi->setThreadingStatus( MessageItem::ImperfectParentFound ); + return pParent; // got an imperfect parent for this message + } + } } - } - return 0; + return 0; } // @@ -1704,584 +1704,584 @@ template< class ItemComparator > static bool messageItemNeedsReSorting( SortOrder::SortDirection messageSortDirection, ItemPrivate *parent, MessageItem *messageItem ) { - if ( ( messageSortDirection == SortOrder::Ascending ) - || ( parent->mType == Item::Message ) ) - { - return parent->childItemNeedsReSorting< ItemComparator, true >( messageItem ); - } - return parent->childItemNeedsReSorting< ItemComparator, false >( messageItem ); + if ( ( messageSortDirection == SortOrder::Ascending ) + || ( parent->mType == Item::Message ) ) + { + return parent->childItemNeedsReSorting< ItemComparator, true >( messageItem ); + } + return parent->childItemNeedsReSorting< ItemComparator, false >( messageItem ); } bool ModelPrivate::handleItemPropertyChanges( int propertyChangeMask, Item * parent, Item * item ) { - // The facts: - // - // - If dates changed: - // - If we're sorting messages by min/max date then at each level the messages might need resorting. - // - If the thread leader is the most recent message of a thread then the uppermost - // message of the thread might need re-grouping. - // - If the groups are sorted by min/max date then the group might need re-sorting too. - // - // This function explicitly doesn't re-apply the filter when ActionItemStatus changes. - // This is because filters must be re-applied due to a broader range of status variations: - // this is done in viewItemJobStepInternalForJobPass1Update() instead (which is the only - // place in that ActionItemStatus may be set). - - if( parent->type() == Item::InvisibleRoot ) - { - // item is either a message or a group attacched to the root. - // It might need resorting. - if ( item->type() == Item::GroupHeader ) - { - // item is a group header attacched to the root. - if ( - ( - // max date changed - ( propertyChangeMask & MaxDateChanged ) && - // groups sorted by max date - ( mSortOrder->groupSorting() == SortOrder::SortGroupsByDateTimeOfMostRecent ) - ) || ( - // date changed - ( propertyChangeMask & DateChanged ) && - // groups sorted by date - ( mSortOrder->groupSorting() == SortOrder::SortGroupsByDateTime ) - ) - ) - { - // This group might need re-sorting. - - // Groups are large container of messages so it's likely that - // another message inserted will cause this group to be marked again. - // So we wait until the end to do the grand final re-sorting: it will be done in Pass4. - mGroupHeadersThatNeedUpdate.insert( static_cast< GroupHeaderItem * >( item ), static_cast< GroupHeaderItem * >( item ) ); - } - } else { - // item is a message. It might need re-sorting. + // The facts: + // + // - If dates changed: + // - If we're sorting messages by min/max date then at each level the messages might need resorting. + // - If the thread leader is the most recent message of a thread then the uppermost + // message of the thread might need re-grouping. + // - If the groups are sorted by min/max date then the group might need re-sorting too. + // + // This function explicitly doesn't re-apply the filter when ActionItemStatus changes. + // This is because filters must be re-applied due to a broader range of status variations: + // this is done in viewItemJobStepInternalForJobPass1Update() instead (which is the only + // place in that ActionItemStatus may be set). + + if( parent->type() == Item::InvisibleRoot ) + { + // item is either a message or a group attacched to the root. + // It might need resorting. + if ( item->type() == Item::GroupHeader ) + { + // item is a group header attacched to the root. + if ( + ( + // max date changed + ( propertyChangeMask & MaxDateChanged ) && + // groups sorted by max date + ( mSortOrder->groupSorting() == SortOrder::SortGroupsByDateTimeOfMostRecent ) + ) || ( + // date changed + ( propertyChangeMask & DateChanged ) && + // groups sorted by date + ( mSortOrder->groupSorting() == SortOrder::SortGroupsByDateTime ) + ) + ) + { + // This group might need re-sorting. + + // Groups are large container of messages so it's likely that + // another message inserted will cause this group to be marked again. + // So we wait until the end to do the grand final re-sorting: it will be done in Pass4. + mGroupHeadersThatNeedUpdate.insert( static_cast< GroupHeaderItem * >( item ), static_cast< GroupHeaderItem * >( item ) ); + } + } else { + // item is a message. It might need re-sorting. + + // Since sorting is an expensive operation, we first check if it's *really* needed. + // Re-sorting will actually not change min/max dates at all and + // will not climb up the parent's ancestor tree. + + switch ( mSortOrder->messageSorting() ) + { + case SortOrder::SortMessagesByDateTime: + if ( propertyChangeMask & DateChanged ) // date changed + { + if ( messageItemNeedsReSorting< ItemDateComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) + attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); + } // else date changed, but it doesn't match sorting order: no need to re-sort + break; + case SortOrder::SortMessagesByDateTimeOfMostRecent: + if ( propertyChangeMask & MaxDateChanged ) // max date changed + { + if ( messageItemNeedsReSorting< ItemMaxDateComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) + attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); + } // else max date changed, but it doesn't match sorting order: no need to re-sort + break; + case SortOrder::SortMessagesByActionItemStatus: + if ( propertyChangeMask & ActionItemStatusChanged ) // todo status changed + { + if ( messageItemNeedsReSorting< ItemActionItemStatusComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) + attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); + } // else to do status changed, but it doesn't match sorting order: no need to re-sort + break; + case SortOrder::SortMessagesByUnreadStatus: + if ( propertyChangeMask & UnreadStatusChanged ) // new / unread status changed + { + if ( messageItemNeedsReSorting< ItemUnreadStatusComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) + attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); + } // else new/unread status changed, but it doesn't match sorting order: no need to re-sort + break; + case SortOrder::SortMessagesByImportantStatus: + if ( propertyChangeMask & ImportantStatusChanged ) // important status changed + { + if ( messageItemNeedsReSorting< ItemImportantStatusComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) + attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); + } // else new/unread status changed, but it doesn't match sorting order: no need to re-sort + break; + default: + // this kind of message sorting isn't affected by the property changes: nothing to do. + break; + } + } + + return false; // the invisible root isn't affected by any change. + } - // Since sorting is an expensive operation, we first check if it's *really* needed. - // Re-sorting will actually not change min/max dates at all and - // will not climb up the parent's ancestor tree. - - switch ( mSortOrder->messageSorting() ) - { - case SortOrder::SortMessagesByDateTime: - if ( propertyChangeMask & DateChanged ) // date changed - { + if ( parent->type() == Item::GroupHeader ) + { + // item is a message attacched to a GroupHeader. + // It might need re-grouping or re-sorting (within the same group) + + // Check re-grouping here. + if ( + ( + // max date changed + ( propertyChangeMask & MaxDateChanged ) && + // thread leader is most recent message + ( mAggregation->threadLeader() == Aggregation::MostRecentMessage ) + ) || ( + // date changed + ( propertyChangeMask & DateChanged ) && + // thread leader the topmost message + ( mAggregation->threadLeader() == Aggregation::TopmostMessage ) + ) + ) + { + // Might really need re-grouping. + // attachMessageToGroupHeader() will find the right group for this message + // and if it's different than the current it will move it. + attachMessageToGroupHeader( static_cast< MessageItem * >( item ) ); + // Re-grouping fixes the properties of the involved group headers + // so at exit of attachMessageToGroupHeader() the parent can't be affected + // by the change anymore. + return false; + } + + // Re-grouping wasn't needed. Re-sorting might be. + + } // else item is a message attacched to another message and might need re-sorting only. + + // Check if message needs re-sorting. + + switch ( mSortOrder->messageSorting() ) + { + case SortOrder::SortMessagesByDateTime: + if ( propertyChangeMask & DateChanged ) // date changed + { if ( messageItemNeedsReSorting< ItemDateComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) - attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); - } // else date changed, but it doesn't match sorting order: no need to re-sort + attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); + } // else date changed, but it doesn't match sorting order: no need to re-sort break; - case SortOrder::SortMessagesByDateTimeOfMostRecent: - if ( propertyChangeMask & MaxDateChanged ) // max date changed - { + case SortOrder::SortMessagesByDateTimeOfMostRecent: + if ( propertyChangeMask & MaxDateChanged ) // max date changed + { if ( messageItemNeedsReSorting< ItemMaxDateComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) - attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); - } // else max date changed, but it doesn't match sorting order: no need to re-sort + attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); + } // else max date changed, but it doesn't match sorting order: no need to re-sort break; - case SortOrder::SortMessagesByActionItemStatus: - if ( propertyChangeMask & ActionItemStatusChanged ) // todo status changed - { + case SortOrder::SortMessagesByActionItemStatus: + if ( propertyChangeMask & ActionItemStatusChanged ) // todo status changed + { if ( messageItemNeedsReSorting< ItemActionItemStatusComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) - attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); - } // else to do status changed, but it doesn't match sorting order: no need to re-sort + attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); + } // else to do status changed, but it doesn't match sorting order: no need to re-sort break; - case SortOrder::SortMessagesByUnreadStatus: - if ( propertyChangeMask & UnreadStatusChanged ) // new / unread status changed - { + case SortOrder::SortMessagesByUnreadStatus: + if ( propertyChangeMask & UnreadStatusChanged ) // new / unread status changed + { if ( messageItemNeedsReSorting< ItemUnreadStatusComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) - attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); - } // else new/unread status changed, but it doesn't match sorting order: no need to re-sort + attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); + } // else new/unread status changed, but it doesn't match sorting order: no need to re-sort break; - case SortOrder::SortMessagesByImportantStatus: - if ( propertyChangeMask & ImportantStatusChanged ) // important status changed - { + case SortOrder::SortMessagesByImportantStatus: + if ( propertyChangeMask & ImportantStatusChanged ) // important status changed + { if ( messageItemNeedsReSorting< ItemImportantStatusComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) - attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); - } // else new/unread status changed, but it doesn't match sorting order: no need to re-sort + attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); + } // else important status changed, but it doesn't match sorting order: no need to re-sort break; - default: - // this kind of message sorting isn't affected by the property changes: nothing to do. + default: + // this kind of message sorting isn't affected by property changes: nothing to do. break; - } } - return false; // the invisible root isn't affected by any change. - } + return true; // parent might be affected too. +} - if ( parent->type() == Item::GroupHeader ) - { - // item is a message attacched to a GroupHeader. - // It might need re-grouping or re-sorting (within the same group) +void ModelPrivate::messageDetachedUpdateParentProperties( Item *oldParent, MessageItem *mi ) +{ + Q_ASSERT( oldParent ); + Q_ASSERT( mi ); + Q_ASSERT( oldParent != mRootItem ); - // Check re-grouping here. - if ( - ( - // max date changed - ( propertyChangeMask & MaxDateChanged ) && - // thread leader is most recent message - ( mAggregation->threadLeader() == Aggregation::MostRecentMessage ) - ) || ( - // date changed - ( propertyChangeMask & DateChanged ) && - // thread leader the topmost message - ( mAggregation->threadLeader() == Aggregation::TopmostMessage ) - ) - ) - { - // Might really need re-grouping. - // attachMessageToGroupHeader() will find the right group for this message - // and if it's different than the current it will move it. - attachMessageToGroupHeader( static_cast< MessageItem * >( item ) ); - // Re-grouping fixes the properties of the involved group headers - // so at exit of attachMessageToGroupHeader() the parent can't be affected - // by the change anymore. - return false; - } - // Re-grouping wasn't needed. Re-sorting might be. + // oldParent might have its properties changed because of the child removal. + // propagate the changes up. + for(;;) + { + // pParent is not the root item now. This is assured by how we enter this loop + // and by the fact that handleItemPropertyChanges returns false when grandParent + // is Item::InvisibleRoot. We could actually assert it here... - } // else item is a message attacched to another message and might need re-sorting only. + // Check if its dates need an update. + int propertyChangeMask; - // Check if message needs re-sorting. + if ( ( mi->maxDate() == oldParent->maxDate() ) && oldParent->recomputeMaxDate() ) + propertyChangeMask = MaxDateChanged; + else + break; // from the for(;;) loop - switch ( mSortOrder->messageSorting() ) - { - case SortOrder::SortMessagesByDateTime: - if ( propertyChangeMask & DateChanged ) // date changed - { - if ( messageItemNeedsReSorting< ItemDateComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) - attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); - } // else date changed, but it doesn't match sorting order: no need to re-sort - break; - case SortOrder::SortMessagesByDateTimeOfMostRecent: - if ( propertyChangeMask & MaxDateChanged ) // max date changed - { - if ( messageItemNeedsReSorting< ItemMaxDateComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) - attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); - } // else max date changed, but it doesn't match sorting order: no need to re-sort - break; - case SortOrder::SortMessagesByActionItemStatus: - if ( propertyChangeMask & ActionItemStatusChanged ) // todo status changed - { - if ( messageItemNeedsReSorting< ItemActionItemStatusComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) - attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); - } // else to do status changed, but it doesn't match sorting order: no need to re-sort - break; - case SortOrder::SortMessagesByUnreadStatus: - if ( propertyChangeMask & UnreadStatusChanged ) // new / unread status changed - { - if ( messageItemNeedsReSorting< ItemUnreadStatusComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) - attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); - } // else new/unread status changed, but it doesn't match sorting order: no need to re-sort - break; - case SortOrder::SortMessagesByImportantStatus: - if ( propertyChangeMask & ImportantStatusChanged ) // important status changed - { - if ( messageItemNeedsReSorting< ItemImportantStatusComparator >( mSortOrder->messageSortDirection(), parent->d_ptr, static_cast< MessageItem * >( item ) ) ) - attachMessageToParent( parent, static_cast< MessageItem * >( item ) ); - } // else important status changed, but it doesn't match sorting order: no need to re-sort - break; - default: - // this kind of message sorting isn't affected by property changes: nothing to do. - break; - } + // One of the oldParent properties has changed for sure - return true; // parent might be affected too. + Item * grandParent = oldParent->parent(); + + // If there is no grandParent then oldParent isn't attacched to the view. + // Re-sorting / re-grouping isn't needed for sure. + if ( !grandParent ) + break; // from the for(;;) loop + + // The following function will return true if grandParent may be affected by the change. + // If the grandParent isn't affected, we stop climbing. + if ( !handleItemPropertyChanges( propertyChangeMask, grandParent, oldParent ) ) + break; // from the for(;;) loop + + // Now we need to climb up one level and check again. + oldParent = grandParent; + } // for(;;) loop + + // If the last message was removed from a group header then this group will need an update + // for sure. We will need to remove it (unless a message is attacched back to it) + if ( oldParent->type() == Item::GroupHeader ) + { + if ( oldParent->childItemCount() == 0 ) + mGroupHeadersThatNeedUpdate.insert( static_cast< GroupHeaderItem * >( oldParent ), static_cast< GroupHeaderItem * >( oldParent ) ); + } } -void ModelPrivate::messageDetachedUpdateParentProperties( Item *oldParent, MessageItem *mi ) +void ModelPrivate::propagateItemPropertiesToParent( Item * item ) { - Q_ASSERT( oldParent ); - Q_ASSERT( mi ); - Q_ASSERT( oldParent != mRootItem ); - - - // oldParent might have its properties changed because of the child removal. - // propagate the changes up. - for(;;) - { - // pParent is not the root item now. This is assured by how we enter this loop - // and by the fact that handleItemPropertyChanges returns false when grandParent - // is Item::InvisibleRoot. We could actually assert it here... + Item * pParent = item->parent(); + Q_ASSERT( pParent ); + Q_ASSERT( pParent != mRootItem ); - // Check if its dates need an update. - int propertyChangeMask; + for(;;) + { + // pParent is not the root item now. This is assured by how we enter this loop + // and by the fact that handleItemPropertyChanges returns false when grandParent + // is Item::InvisibleRoot. We could actually assert it here... - if ( ( mi->maxDate() == oldParent->maxDate() ) && oldParent->recomputeMaxDate() ) - propertyChangeMask = MaxDateChanged; - else - break; // from the for(;;) loop + // Check if its dates need an update. + int propertyChangeMask; - // One of the oldParent properties has changed for sure + if ( item->maxDate() > pParent->maxDate() ) + { + pParent->setMaxDate( item->maxDate() ); + propertyChangeMask = MaxDateChanged; + } else { + // No parent dates have changed: no further work is needed. Stop climbing here. + break; // from the for(;;) loop + } - Item * grandParent = oldParent->parent(); + // One of the pParent properties has changed. - // If there is no grandParent then oldParent isn't attacched to the view. - // Re-sorting / re-grouping isn't needed for sure. - if ( !grandParent ) - break; // from the for(;;) loop - - // The following function will return true if grandParent may be affected by the change. - // If the grandParent isn't affected, we stop climbing. - if ( !handleItemPropertyChanges( propertyChangeMask, grandParent, oldParent ) ) - break; // from the for(;;) loop - - // Now we need to climb up one level and check again. - oldParent = grandParent; - } // for(;;) loop - - // If the last message was removed from a group header then this group will need an update - // for sure. We will need to remove it (unless a message is attacched back to it) - if ( oldParent->type() == Item::GroupHeader ) - { - if ( oldParent->childItemCount() == 0 ) - mGroupHeadersThatNeedUpdate.insert( static_cast< GroupHeaderItem * >( oldParent ), static_cast< GroupHeaderItem * >( oldParent ) ); - } + Item * grandParent = pParent->parent(); + + // If there is no grandParent then pParent isn't attacched to the view. + // Re-sorting / re-grouping isn't needed for sure. + if ( !grandParent ) + break; // from the for(;;) loop + + // The following function will return true if grandParent may be affected by the change. + // If the grandParent isn't affected, we stop climbing. + if ( !handleItemPropertyChanges( propertyChangeMask, grandParent, pParent ) ) + break; // from the for(;;) loop + + // Now we need to climb up one level and check again. + pParent = grandParent; + + } // for(;;) } -void ModelPrivate::propagateItemPropertiesToParent( Item * item ) + +void ModelPrivate::attachMessageToParent( Item *pParent, MessageItem *mi ) { - Item * pParent = item->parent(); - Q_ASSERT( pParent ); - Q_ASSERT( pParent != mRootItem ); - - for(;;) - { - // pParent is not the root item now. This is assured by how we enter this loop - // and by the fact that handleItemPropertyChanges returns false when grandParent - // is Item::InvisibleRoot. We could actually assert it here... + Q_ASSERT( pParent ); + Q_ASSERT( mi ); - // Check if its dates need an update. - int propertyChangeMask; + // This function may be called to do a simple "re-sort" of the item inside the parent. + // In that case mi->parent() is equal to pParent. + bool oldParentWasTheSame; - if ( item->maxDate() > pParent->maxDate() ) + if ( mi->parent() ) { - pParent->setMaxDate( item->maxDate() ); - propertyChangeMask = MaxDateChanged; - } else { - // No parent dates have changed: no further work is needed. Stop climbing here. - break; // from the for(;;) loop - } + Item * oldParent = mi->parent(); - // One of the pParent properties has changed. + // The item already had a parent and this means that we're moving it. + oldParentWasTheSame = oldParent == pParent; // just re-sorting ? - Item * grandParent = pParent->parent(); + if ( mi->isViewable() ) // is actually + { + // The message is actually attached to the viewable root - // If there is no grandParent then pParent isn't attacched to the view. - // Re-sorting / re-grouping isn't needed for sure. - if ( !grandParent ) - break; // from the for(;;) loop + // Unfortunately we need to hack the model/view architecture + // since it's somewhat flawed in this. At the moment of writing + // there is simply no way to atomically move a subtree. + // We must detach, call beginRemoveRows()/endRemoveRows(), + // save the expanded state, save the selection, save the current item, + // save the view position (YES! As we are removing items the view + // will hopelessly jump around so we're just FORCED to break + // the isolation from the view)... + // ...*then* reattach, restore the expanded state, restore the selection, + // restore the current item, restore the view position and pray + // that nothing will fail in the (rather complicated) process.... + + // Yet more unfortunately, while saving the expanded state might stop + // at a certain (unexpanded) point in the tree, saving the selection + // is hopelessly recursive down to the bare leafs. + + // Furthermore the expansion of items is a common case while selection + // in the subtree is rare, so saving it would be a huge cost with + // a low revenue. + + // This is why we just let the selection screw up. I hereby refuse to call + // yet another expensive recursive function here :D + + // The current item saving can be somewhat optimized doing it once for + // a single job step... + + if ( + ( ( mi )->childItemCount() > 0 ) && // has children + mModelForItemFunctions && // the UI is not actually disconnected + mView->isExpanded( q->index( mi, 0 ) ) // is actually expanded + ) + saveExpandedStateOfSubtree( mi ); + } - // The following function will return true if grandParent may be affected by the change. - // If the grandParent isn't affected, we stop climbing. - if ( !handleItemPropertyChanges( propertyChangeMask, grandParent, pParent ) ) - break; // from the for(;;) loop + // If the parent is viewable (so mi was viewable too) then the beginRemoveRows() + // and endRemoveRows() functions of this model will be called too. + oldParent->takeChildItem( mModelForItemFunctions, mi ); - // Now we need to climb up one level and check again. - pParent = grandParent; + if ( ( !oldParentWasTheSame ) && ( oldParent != mRootItem ) ) + messageDetachedUpdateParentProperties( oldParent, mi ); - } // for(;;) -} + } else { + // The item had no parent yet. + oldParentWasTheSame = false; + } + // Take care of perfect / imperfect threading. + // Items that are now perfectly threaded, but already have a different parent + // might have been imperfectly threaded before. Remove them from the caches. + // Items that are now imperfectly threaded must be added to the caches. + // + // If we're just re-sorting the item inside the same parent then the threading + // caches don't need to be updated (since they actually depend on the parent). -void ModelPrivate::attachMessageToParent( Item *pParent, MessageItem *mi ) -{ - Q_ASSERT( pParent ); - Q_ASSERT( mi ); + if ( !oldParentWasTheSame ) + { + switch( mi->threadingStatus() ) + { + case MessageItem::PerfectParentFound: + if ( !mi->inReplyToIdMD5().isEmpty() ) + mThreadingCacheMessageInReplyToIdMD5ToMessageItem.remove( mi->inReplyToIdMD5(), mi ); + break; + case MessageItem::ImperfectParentFound: + case MessageItem::ParentMissing: // may be: temporary or just fallback assignment + if ( !mi->inReplyToIdMD5().isEmpty() ) + { + if ( !mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains( mi->inReplyToIdMD5(), mi ) ) + mThreadingCacheMessageInReplyToIdMD5ToMessageItem.insert( mi->inReplyToIdMD5(), mi ); + } + break; + case MessageItem::NonThreadable: // this also happens when we do no threading at all + // make gcc happy + Q_ASSERT( !mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains( mi->inReplyToIdMD5(), mi ) ); + break; + } + } + + // Set the new parent + mi->setParent( pParent ); + + // Propagate watched and ignored status + if ( + ( pParent->status().toQInt32() & mCachedWatchedOrIgnoredStatusBits ) && // unlikely + ( pParent->type() == Item::Message ) // likely + ) + { + // the parent is either watched or ignored: propagate to the child + if ( pParent->status().isWatched() ) + { + int row = mInvariantRowMapper->modelInvariantIndexToModelIndexRow( mi ); + mi->setStatus( Akonadi::MessageStatus::statusWatched() ); + mStorageModel->setMessageItemStatus( mi, row, Akonadi::MessageStatus::statusWatched() ); + } else if ( pParent->status().isIgnored() ) + { + int row = mInvariantRowMapper->modelInvariantIndexToModelIndexRow( mi ); + mi->setStatus( Akonadi::MessageStatus::statusIgnored() ); + mStorageModel->setMessageItemStatus( mi, row, Akonadi::MessageStatus::statusIgnored() ); + } + } + + // And insert into its child list - // This function may be called to do a simple "re-sort" of the item inside the parent. - // In that case mi->parent() is equal to pParent. - bool oldParentWasTheSame; - - if ( mi->parent() ) - { - Item * oldParent = mi->parent(); - - // The item already had a parent and this means that we're moving it. - oldParentWasTheSame = oldParent == pParent; // just re-sorting ? - - if ( mi->isViewable() ) // is actually - { - // The message is actually attached to the viewable root - - // Unfortunately we need to hack the model/view architecture - // since it's somewhat flawed in this. At the moment of writing - // there is simply no way to atomically move a subtree. - // We must detach, call beginRemoveRows()/endRemoveRows(), - // save the expanded state, save the selection, save the current item, - // save the view position (YES! As we are removing items the view - // will hopelessly jump around so we're just FORCED to break - // the isolation from the view)... - // ...*then* reattach, restore the expanded state, restore the selection, - // restore the current item, restore the view position and pray - // that nothing will fail in the (rather complicated) process.... - - // Yet more unfortunately, while saving the expanded state might stop - // at a certain (unexpanded) point in the tree, saving the selection - // is hopelessly recursive down to the bare leafs. - - // Furthermore the expansion of items is a common case while selection - // in the subtree is rare, so saving it would be a huge cost with - // a low revenue. - - // This is why we just let the selection screw up. I hereby refuse to call - // yet another expensive recursive function here :D - - // The current item saving can be somewhat optimized doing it once for - // a single job step... - - if ( - ( ( mi )->childItemCount() > 0 ) && // has children - mModelForItemFunctions && // the UI is not actually disconnected - mView->isExpanded( q->index( mi, 0 ) ) // is actually expanded - ) - saveExpandedStateOfSubtree( mi ); - } - - // If the parent is viewable (so mi was viewable too) then the beginRemoveRows() - // and endRemoveRows() functions of this model will be called too. - oldParent->takeChildItem( mModelForItemFunctions, mi ); - - if ( ( !oldParentWasTheSame ) && ( oldParent != mRootItem ) ) - messageDetachedUpdateParentProperties( oldParent, mi ); - - } else { - // The item had no parent yet. - oldParentWasTheSame = false; - } - - // Take care of perfect / imperfect threading. - // Items that are now perfectly threaded, but already have a different parent - // might have been imperfectly threaded before. Remove them from the caches. - // Items that are now imperfectly threaded must be added to the caches. - // - // If we're just re-sorting the item inside the same parent then the threading - // caches don't need to be updated (since they actually depend on the parent). - - if ( !oldParentWasTheSame ) - { - switch( mi->threadingStatus() ) - { - case MessageItem::PerfectParentFound: - if ( !mi->inReplyToIdMD5().isEmpty() ) - mThreadingCacheMessageInReplyToIdMD5ToMessageItem.remove( mi->inReplyToIdMD5(), mi ); - break; - case MessageItem::ImperfectParentFound: - case MessageItem::ParentMissing: // may be: temporary or just fallback assignment - if ( !mi->inReplyToIdMD5().isEmpty() ) - { - if ( !mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains( mi->inReplyToIdMD5(), mi ) ) - mThreadingCacheMessageInReplyToIdMD5ToMessageItem.insert( mi->inReplyToIdMD5(), mi ); - } - break; - case MessageItem::NonThreadable: // this also happens when we do no threading at all - // make gcc happy - Q_ASSERT( !mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains( mi->inReplyToIdMD5(), mi ) ); - break; - } - } - - // Set the new parent - mi->setParent( pParent ); - - // Propagate watched and ignored status - if ( - ( pParent->status().toQInt32() & mCachedWatchedOrIgnoredStatusBits ) && // unlikely - ( pParent->type() == Item::Message ) // likely - ) - { - // the parent is either watched or ignored: propagate to the child - if ( pParent->status().isWatched() ) - { - int row = mInvariantRowMapper->modelInvariantIndexToModelIndexRow( mi ); - mi->setStatus( Akonadi::MessageStatus::statusWatched() ); - mStorageModel->setMessageItemStatus( mi, row, Akonadi::MessageStatus::statusWatched() ); - } else if ( pParent->status().isIgnored() ) - { - int row = mInvariantRowMapper->modelInvariantIndexToModelIndexRow( mi ); - mi->setStatus( Akonadi::MessageStatus::statusIgnored() ); - mStorageModel->setMessageItemStatus( mi, row, Akonadi::MessageStatus::statusIgnored() ); - } - } - - // And insert into its child list - - // If pParent is viewable then the insert/append functions will call this model's - // beginInsertRows() and endInsertRows() functions. This is EXTREMELY - // expensive and ugly but it's the only way with the Qt4 imposed Model/View method. - // Dude... (citation from Lost, if it wasn't clear). - - // I'm using a macro since it does really improve readability. - // I'm NOT using a helper function since gcc will refuse to inline some of - // the calls because they make this function grow too much. + // If pParent is viewable then the insert/append functions will call this model's + // beginInsertRows() and endInsertRows() functions. This is EXTREMELY + // expensive and ugly but it's the only way with the Qt4 imposed Model/View method. + // Dude... (citation from Lost, if it wasn't clear). + + // I'm using a macro since it does really improve readability. + // I'm NOT using a helper function since gcc will refuse to inline some of + // the calls because they make this function grow too much. #define INSERT_MESSAGE_WITH_COMPARATOR( _ItemComparator ) \ - if ( ( mSortOrder->messageSortDirection() == SortOrder::Ascending ) \ + if ( ( mSortOrder->messageSortDirection() == SortOrder::Ascending ) \ || ( pParent->type() == Item::Message ) ) \ - { \ + { \ pParent->d_ptr->insertChildItem< _ItemComparator, true >( mModelForItemFunctions, mi ); \ - } \ - else \ - { \ +} \ + else \ + { \ pParent->d_ptr->insertChildItem< _ItemComparator, false >( mModelForItemFunctions, mi ); \ - } +} - // If pParent is viewable then the insertion call will also set the child state to viewable. - // Since mi MAY have children, then this call may make them viewable. - switch( mSortOrder->messageSorting() ) - { + // If pParent is viewable then the insertion call will also set the child state to viewable. + // Since mi MAY have children, then this call may make them viewable. + switch( mSortOrder->messageSorting() ) + { case SortOrder::SortMessagesByDateTime: - INSERT_MESSAGE_WITH_COMPARATOR( ItemDateComparator ) - break; + INSERT_MESSAGE_WITH_COMPARATOR( ItemDateComparator ) + break; case SortOrder::SortMessagesByDateTimeOfMostRecent: - INSERT_MESSAGE_WITH_COMPARATOR( ItemMaxDateComparator ) - break; + INSERT_MESSAGE_WITH_COMPARATOR( ItemMaxDateComparator ) + break; case SortOrder::SortMessagesBySize: - INSERT_MESSAGE_WITH_COMPARATOR( ItemSizeComparator ) - break; + INSERT_MESSAGE_WITH_COMPARATOR( ItemSizeComparator ) + break; case SortOrder::SortMessagesBySenderOrReceiver: - INSERT_MESSAGE_WITH_COMPARATOR( ItemSenderOrReceiverComparator ) - break; + INSERT_MESSAGE_WITH_COMPARATOR( ItemSenderOrReceiverComparator ) + break; case SortOrder::SortMessagesBySender: - INSERT_MESSAGE_WITH_COMPARATOR( ItemSenderComparator ) - break; + INSERT_MESSAGE_WITH_COMPARATOR( ItemSenderComparator ) + break; case SortOrder::SortMessagesByReceiver: - INSERT_MESSAGE_WITH_COMPARATOR( ItemReceiverComparator ) - break; + INSERT_MESSAGE_WITH_COMPARATOR( ItemReceiverComparator ) + break; case SortOrder::SortMessagesBySubject: - INSERT_MESSAGE_WITH_COMPARATOR( ItemSubjectComparator ) - break; + INSERT_MESSAGE_WITH_COMPARATOR( ItemSubjectComparator ) + break; case SortOrder::SortMessagesByActionItemStatus: - INSERT_MESSAGE_WITH_COMPARATOR( ItemActionItemStatusComparator ) - break; + INSERT_MESSAGE_WITH_COMPARATOR( ItemActionItemStatusComparator ) + break; case SortOrder::SortMessagesByUnreadStatus: - INSERT_MESSAGE_WITH_COMPARATOR( ItemUnreadStatusComparator ) - break; + INSERT_MESSAGE_WITH_COMPARATOR( ItemUnreadStatusComparator ) + break; case SortOrder::SortMessagesByImportantStatus: - INSERT_MESSAGE_WITH_COMPARATOR( ItemImportantStatusComparator ) - break; + INSERT_MESSAGE_WITH_COMPARATOR( ItemImportantStatusComparator ) + break; case SortOrder::NoMessageSorting: - pParent->appendChildItem( mModelForItemFunctions, mi ); - break; + pParent->appendChildItem( mModelForItemFunctions, mi ); + break; default: // should never happen - pParent->appendChildItem( mModelForItemFunctions, mi ); - break; - } - - // Decide if we need to expand parents - bool childNeedsExpanding = ( mi->initialExpandStatus() == Item::ExpandNeeded ); - - if ( pParent->initialExpandStatus() == Item::NoExpandNeeded ) - { - switch( mAggregation->threadExpandPolicy() ) + pParent->appendChildItem( mModelForItemFunctions, mi ); + break; + } + + // Decide if we need to expand parents + bool childNeedsExpanding = ( mi->initialExpandStatus() == Item::ExpandNeeded ); + + if ( pParent->initialExpandStatus() == Item::NoExpandNeeded ) { - case Aggregation::NeverExpandThreads: - // just do nothing unless this child has children and is already marked for expansion - if ( childNeedsExpanding ) - pParent->setInitialExpandStatus( Item::ExpandNeeded ); - break; - case Aggregation::ExpandThreadsWithNewMessages: // No more new status. fall through to unread if it exists in config - case Aggregation::ExpandThreadsWithUnreadMessages: - // expand only if unread (or it has children marked for expansion) - if ( childNeedsExpanding || !mi->status().isRead() ) - pParent->setInitialExpandStatus( Item::ExpandNeeded ); - break; - case Aggregation::ExpandThreadsWithUnreadOrImportantMessages: - // expand only if unread, important or todo (or it has children marked for expansion) - // FIXME: Wouldn't it be nice to be able to test for bitmasks in MessageStatus ? - if ( childNeedsExpanding || !mi->status().isRead() || mi->status().isImportant() || mi->status().isToAct() ) - pParent->setInitialExpandStatus( Item::ExpandNeeded ); - break; - case Aggregation::AlwaysExpandThreads: - // expand everything - pParent->setInitialExpandStatus( Item::ExpandNeeded ); - break; - default: - // BUG - break; - } - } // else it's already marked for expansion or expansion has been already executed - - // expand parent first, if possible - if ( pParent->initialExpandStatus() == Item::ExpandNeeded ) - { - // If UI is not disconnected and parent is viewable, go up and expand - if ( mModelForItemFunctions && pParent->isViewable() ) - { - // Now expand parents as needed - Item * parentToExpand = pParent; - while ( parentToExpand ) - { - if ( parentToExpand == mRootItem ) - break; // no need to set it expanded - // parentToExpand is surely viewable (because this item is) - if ( parentToExpand->initialExpandStatus() == Item::ExpandExecuted ) - break; - - mView->expand( q->index( parentToExpand, 0 ) ); - - parentToExpand->setInitialExpandStatus( Item::ExpandExecuted ); - parentToExpand = parentToExpand->parent(); - } - } else { - // It isn't viewable or UI is disconnected: climb up marking only - Item * parentToExpand = pParent->parent(); - while ( parentToExpand ) - { - if ( parentToExpand == mRootItem ) - break; // no need to set it expanded - parentToExpand->setInitialExpandStatus( Item::ExpandNeeded ); - parentToExpand = parentToExpand->parent(); - } - } - } - - if ( mi->isViewable() ) - { - // mi is now viewable - - // sync subtree expanded status - if ( childNeedsExpanding ) - { - if ( mi->childItemCount() > 0 ) - if ( mModelForItemFunctions ) // the UI is not disconnected - syncExpandedStateOfSubtree( mi ); // sync the real state in the view + switch( mAggregation->threadExpandPolicy() ) + { + case Aggregation::NeverExpandThreads: + // just do nothing unless this child has children and is already marked for expansion + if ( childNeedsExpanding ) + pParent->setInitialExpandStatus( Item::ExpandNeeded ); + break; + case Aggregation::ExpandThreadsWithNewMessages: // No more new status. fall through to unread if it exists in config + case Aggregation::ExpandThreadsWithUnreadMessages: + // expand only if unread (or it has children marked for expansion) + if ( childNeedsExpanding || !mi->status().isRead() ) + pParent->setInitialExpandStatus( Item::ExpandNeeded ); + break; + case Aggregation::ExpandThreadsWithUnreadOrImportantMessages: + // expand only if unread, important or todo (or it has children marked for expansion) + // FIXME: Wouldn't it be nice to be able to test for bitmasks in MessageStatus ? + if ( childNeedsExpanding || !mi->status().isRead() || mi->status().isImportant() || mi->status().isToAct() ) + pParent->setInitialExpandStatus( Item::ExpandNeeded ); + break; + case Aggregation::AlwaysExpandThreads: + // expand everything + pParent->setInitialExpandStatus( Item::ExpandNeeded ); + break; + default: + // BUG + break; + } + } // else it's already marked for expansion or expansion has been already executed + + // expand parent first, if possible + if ( pParent->initialExpandStatus() == Item::ExpandNeeded ) + { + // If UI is not disconnected and parent is viewable, go up and expand + if ( mModelForItemFunctions && pParent->isViewable() ) + { + // Now expand parents as needed + Item * parentToExpand = pParent; + while ( parentToExpand ) + { + if ( parentToExpand == mRootItem ) + break; // no need to set it expanded + // parentToExpand is surely viewable (because this item is) + if ( parentToExpand->initialExpandStatus() == Item::ExpandExecuted ) + break; + + mView->expand( q->index( parentToExpand, 0 ) ); + + parentToExpand->setInitialExpandStatus( Item::ExpandExecuted ); + parentToExpand = parentToExpand->parent(); + } + } else { + // It isn't viewable or UI is disconnected: climb up marking only + Item * parentToExpand = pParent->parent(); + while ( parentToExpand ) + { + if ( parentToExpand == mRootItem ) + break; // no need to set it expanded + parentToExpand->setInitialExpandStatus( Item::ExpandNeeded ); + parentToExpand = parentToExpand->parent(); + } + } } - // apply the filter, if needed - if ( mFilter ) + if ( mi->isViewable() ) { - Q_ASSERT( mModelForItemFunctions ); // the UI must be NOT disconnected here + // mi is now viewable - // apply the filter to subtree - if ( applyFilterToSubtree( mi, q->index( pParent, 0 ) ) ) - { - // mi matched, expand parents (unconditionally) - mView->ensureDisplayedWithParentsExpanded( mi ); - } - } - } - - // Now we need to propagate the property changes the upper levels. - - // If we have just inserted a message inside the root then no work needs to be done: - // no grouping is in effect and the message is already in the right place. - if ( pParent == mRootItem ) - return; - - // If we have just removed the item from this parent and re-inserted it - // then this operation was a simple re-sort. The code above didn't update - // the properties when removing the item so we don't actually need - // to make the updates back. - if ( oldParentWasTheSame ) - return; + // sync subtree expanded status + if ( childNeedsExpanding ) + { + if ( mi->childItemCount() > 0 ) + if ( mModelForItemFunctions ) // the UI is not disconnected + syncExpandedStateOfSubtree( mi ); // sync the real state in the view + } - // FIXME: OPTIMIZE THIS: First propagate changes THEN syncExpandedStateOfSubtree() - // and applyFilterToSubtree... (needs some thinking though). + // apply the filter, if needed + if ( mFilter ) + { + Q_ASSERT( mModelForItemFunctions ); // the UI must be NOT disconnected here + + // apply the filter to subtree + if ( applyFilterToSubtree( mi, q->index( pParent, 0 ) ) ) + { + // mi matched, expand parents (unconditionally) + mView->ensureDisplayedWithParentsExpanded( mi ); + } + } + } + + // Now we need to propagate the property changes the upper levels. - // Time to propagate up. - propagateItemPropertiesToParent( mi ); + // If we have just inserted a message inside the root then no work needs to be done: + // no grouping is in effect and the message is already in the right place. + if ( pParent == mRootItem ) + return; + + // If we have just removed the item from this parent and re-inserted it + // then this operation was a simple re-sort. The code above didn't update + // the properties when removing the item so we don't actually need + // to make the updates back. + if ( oldParentWasTheSame ) + return; - // Aaah.. we're done. Time for a thea ? :) + // FIXME: OPTIMIZE THIS: First propagate changes THEN syncExpandedStateOfSubtree() + // and applyFilterToSubtree... (needs some thinking though). + + // Time to propagate up. + propagateItemPropertiesToParent( mi ); + + // Aaah.. we're done. Time for a thea ? :) } // FIXME: ThreadItem ? @@ -2293,1246 +2293,1246 @@ ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass5( ViewItemJob *job, const QTime &tStart ) { - // In this pass we scan the group headers that are in mGroupHeadersThatNeedUpdate. - // Empty groups get deleted while the other ones are re-sorted. - int elapsed; + // In this pass we scan the group headers that are in mGroupHeadersThatNeedUpdate. + // Empty groups get deleted while the other ones are re-sorted. + int elapsed; - int curIndex = job->currentIndex(); + int curIndex = job->currentIndex(); - QHash< GroupHeaderItem *, GroupHeaderItem * >::Iterator it = mGroupHeadersThatNeedUpdate.begin(); - QHash< GroupHeaderItem *, GroupHeaderItem * >::Iterator end = mGroupHeadersThatNeedUpdate.end(); + QHash< GroupHeaderItem *, GroupHeaderItem * >::Iterator it = mGroupHeadersThatNeedUpdate.begin(); + QHash< GroupHeaderItem *, GroupHeaderItem * >::Iterator end = mGroupHeadersThatNeedUpdate.end(); - while ( it != end ) - { - if ( ( *it )->childItemCount() == 0 ) + while ( it != end ) { - // group with no children, kill it - ( *it )->parent()->takeChildItem( mModelForItemFunctions, *it ); - mGroupHeaderItemHash.remove( ( *it )->label() ); - - // If we were going to restore its position after the job step, well.. we can't do it anymore. - if ( mCurrentItemToRestoreAfterViewItemJobStep == ( *it ) ) - mCurrentItemToRestoreAfterViewItemJobStep = 0; + if ( ( *it )->childItemCount() == 0 ) + { + // group with no children, kill it + ( *it )->parent()->takeChildItem( mModelForItemFunctions, *it ); + mGroupHeaderItemHash.remove( ( *it )->label() ); + + // If we were going to restore its position after the job step, well.. we can't do it anymore. + if ( mCurrentItemToRestoreAfterViewItemJobStep == ( *it ) ) + mCurrentItemToRestoreAfterViewItemJobStep = 0; - // bye bye - delete *it; - } else { - // Group with children: probably needs re-sorting. + // bye bye + delete *it; + } else { + // Group with children: probably needs re-sorting. - // Re-sorting here is an expensive operation. - // In fact groups have been put in the QHash above on the assumption - // that re-sorting *might* be needed but no real (expensive) check - // has been done yet. Also by sorting a single group we might actually - // put the others in the right place. - // So finally check if re-sorting is *really* needed. - bool needsReSorting; + // Re-sorting here is an expensive operation. + // In fact groups have been put in the QHash above on the assumption + // that re-sorting *might* be needed but no real (expensive) check + // has been done yet. Also by sorting a single group we might actually + // put the others in the right place. + // So finally check if re-sorting is *really* needed. + bool needsReSorting; - // A macro really improves readability here. + // A macro really improves readability here. #define CHECK_IF_GROUP_NEEDS_RESORTING( _ItemDateComparator ) \ - switch ( mSortOrder->groupSortDirection() ) \ - { \ - case SortOrder::Ascending: \ - needsReSorting = ( *it )->parent()->d_ptr->childItemNeedsReSorting< _ItemDateComparator, true >( *it ); \ - break; \ - case SortOrder::Descending: \ - needsReSorting = ( *it )->parent()->d_ptr->childItemNeedsReSorting< _ItemDateComparator, false >( *it ); \ - break; \ - default: /* should never happen */ \ - needsReSorting = false; \ - break; \ - } - - switch ( mSortOrder->groupSorting() ) - { - case SortOrder::SortGroupsByDateTime: - CHECK_IF_GROUP_NEEDS_RESORTING( ItemDateComparator ) - break; - case SortOrder::SortGroupsByDateTimeOfMostRecent: - CHECK_IF_GROUP_NEEDS_RESORTING( ItemMaxDateComparator ) - break; - case SortOrder::SortGroupsBySenderOrReceiver: - CHECK_IF_GROUP_NEEDS_RESORTING( ItemSenderOrReceiverComparator ) - break; - case SortOrder::SortGroupsBySender: - CHECK_IF_GROUP_NEEDS_RESORTING( ItemSenderComparator ) - break; - case SortOrder::SortGroupsByReceiver: - CHECK_IF_GROUP_NEEDS_RESORTING( ItemReceiverComparator ) - break; - case SortOrder::NoGroupSorting: - needsReSorting = false; - break; - default: - // Should never happen... just assume re-sorting is not needed - needsReSorting = false; - break; - } + switch ( mSortOrder->groupSortDirection() ) \ + { \ + case SortOrder::Ascending: \ + needsReSorting = ( *it )->parent()->d_ptr->childItemNeedsReSorting< _ItemDateComparator, true >( *it ); \ + break; \ + case SortOrder::Descending: \ + needsReSorting = ( *it )->parent()->d_ptr->childItemNeedsReSorting< _ItemDateComparator, false >( *it ); \ + break; \ + default: /* should never happen */ \ + needsReSorting = false; \ + break; \ + } - if ( needsReSorting ) - attachGroup( *it ); // it will first detach and then re-attach in the proper place - } + switch ( mSortOrder->groupSorting() ) + { + case SortOrder::SortGroupsByDateTime: + CHECK_IF_GROUP_NEEDS_RESORTING( ItemDateComparator ) + break; + case SortOrder::SortGroupsByDateTimeOfMostRecent: + CHECK_IF_GROUP_NEEDS_RESORTING( ItemMaxDateComparator ) + break; + case SortOrder::SortGroupsBySenderOrReceiver: + CHECK_IF_GROUP_NEEDS_RESORTING( ItemSenderOrReceiverComparator ) + break; + case SortOrder::SortGroupsBySender: + CHECK_IF_GROUP_NEEDS_RESORTING( ItemSenderComparator ) + break; + case SortOrder::SortGroupsByReceiver: + CHECK_IF_GROUP_NEEDS_RESORTING( ItemReceiverComparator ) + break; + case SortOrder::NoGroupSorting: + needsReSorting = false; + break; + default: + // Should never happen... just assume re-sorting is not needed + needsReSorting = false; + break; + } - it = mGroupHeadersThatNeedUpdate.erase( it ); + if ( needsReSorting ) + attachGroup( *it ); // it will first detach and then re-attach in the proper place + } - curIndex++; + it = mGroupHeadersThatNeedUpdate.erase( it ); - // FIXME: In fact a single update is likely to manipulate - // a subtree with a LOT of messages inside. If interactivity is favored - // we should check the time really more often. - if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) - { - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - if ( it != mGroupHeadersThatNeedUpdate.end() ) + curIndex++; + + // FIXME: In fact a single update is likely to manipulate + // a subtree with a LOT of messages inside. If interactivity is favored + // we should check the time really more often. + if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) { - job->setCurrentIndex( curIndex ); - return ViewItemJobInterrupted; + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + if ( it != mGroupHeadersThatNeedUpdate.end() ) + { + job->setCurrentIndex( curIndex ); + return ViewItemJobInterrupted; + } + } } - } - } - } + } - return ViewItemJobCompleted; + return ViewItemJobCompleted; } ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass4( ViewItemJob *job, const QTime &tStart ) { - // In this pass we scan mUnassignedMessageListForPass4 which now - // contains both items with parents and items without parents. - // We scan mUnassignedMessageList for messages without parent (the ones that haven't been - // attacched to the viewable tree yet) and find a suitable group for them. Then we simply - // clear mUnassignedMessageList. - - // We call this pass "Grouping" - - int elapsed; - - int curIndex = job->currentIndex(); - int endIndex = job->endIndex(); - - while ( curIndex <= endIndex ) - { - MessageItem * mi = mUnassignedMessageListForPass4[curIndex]; - if ( !mi->parent() ) - { - // Unassigned item: thread leader, insert into the proper group. - // Locate the group (or root if no grouping requested) - attachMessageToGroupHeader( mi ); - } else { - // A parent was already assigned in Pass3: we have nothing to do here - } - curIndex++; + // In this pass we scan mUnassignedMessageListForPass4 which now + // contains both items with parents and items without parents. + // We scan mUnassignedMessageList for messages without parent (the ones that haven't been + // attacched to the viewable tree yet) and find a suitable group for them. Then we simply + // clear mUnassignedMessageList. + + // We call this pass "Grouping" + + int elapsed; - // FIXME: In fact a single call to attachMessageToGroupHeader() is likely to manipulate - // a subtree with a LOT of messages inside. If interactivity is favored - // we should check the time really more often. - if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) + int curIndex = job->currentIndex(); + int endIndex = job->endIndex(); + + while ( curIndex <= endIndex ) { - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - if ( curIndex <= endIndex ) + MessageItem * mi = mUnassignedMessageListForPass4[curIndex]; + if ( !mi->parent() ) { - job->setCurrentIndex( curIndex ); - return ViewItemJobInterrupted; + // Unassigned item: thread leader, insert into the proper group. + // Locate the group (or root if no grouping requested) + attachMessageToGroupHeader( mi ); + } else { + // A parent was already assigned in Pass3: we have nothing to do here + } + curIndex++; + + // FIXME: In fact a single call to attachMessageToGroupHeader() is likely to manipulate + // a subtree with a LOT of messages inside. If interactivity is favored + // we should check the time really more often. + if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) + { + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + if ( curIndex <= endIndex ) + { + job->setCurrentIndex( curIndex ); + return ViewItemJobInterrupted; + } + } } - } } - } - mUnassignedMessageListForPass4.clear(); - return ViewItemJobCompleted; + mUnassignedMessageListForPass4.clear(); + return ViewItemJobCompleted; } ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass3( ViewItemJob *job, const QTime &tStart ) { - // In this pass we scan the mUnassignedMessageListForPass3 and try to do construct the threads - // by using subject based threading. If subject based threading is not in effect then - // this pass turns to a nearly-no-op: at the end of Pass2 we have swapped the lists - // and mUnassignedMessageListForPass3 is actually empty. - - // We don't shrink the mUnassignedMessageListForPass3 for two reasons: - // - It would mess up this chunked algorithm by shifting indexes - // - mUnassignedMessageList is a QList which is basically an array. It's faster - // to traverse an array of N entries than to remove K>0 entries one by one and - // to traverse the remaining N-K entries. - - int elapsed; - - int curIndex = job->currentIndex(); - int endIndex = job->endIndex(); - - while ( curIndex <= endIndex ) - { - // If we're here, then threading is requested for sure. - MessageItem * mi = mUnassignedMessageListForPass3[curIndex]; - if ( ( !mi->parent() ) || ( mi->threadingStatus() == MessageItem::ParentMissing ) ) - { - // Parent is missing (either "physically" with the item being not attacched or "logically" - // with the item being attacched to a group or directly to the root. - if ( mi->subjectIsPrefixed() ) - { - // We can try to guess it - MessageItem * mparent = guessMessageParent( mi ); - - if ( mparent ) - { - // imperfect parent found - if ( mi->isViewable() ) - { - // mi was already viewable, we're just trying to re-parent it better... - attachMessageToParent( mparent, mi ); - if ( !mparent->isViewable() ) - { - // re-attach it immediately (so current item is not lost) - MessageItem * topmost = mparent->topmostMessage(); - Q_ASSERT( !topmost->parent() ); // groups are always viewable! - topmost->setThreadingStatus( MessageItem::ParentMissing ); - attachMessageToGroupHeader( topmost ); - } - } else { - // mi wasn't viewable yet.. no need to attach parent - attachMessageToParent( mparent, mi ); - } - // and we're done for now + // In this pass we scan the mUnassignedMessageListForPass3 and try to do construct the threads + // by using subject based threading. If subject based threading is not in effect then + // this pass turns to a nearly-no-op: at the end of Pass2 we have swapped the lists + // and mUnassignedMessageListForPass3 is actually empty. + + // We don't shrink the mUnassignedMessageListForPass3 for two reasons: + // - It would mess up this chunked algorithm by shifting indexes + // - mUnassignedMessageList is a QList which is basically an array. It's faster + // to traverse an array of N entries than to remove K>0 entries one by one and + // to traverse the remaining N-K entries. + + int elapsed; + + int curIndex = job->currentIndex(); + int endIndex = job->endIndex(); + + while ( curIndex <= endIndex ) + { + // If we're here, then threading is requested for sure. + MessageItem * mi = mUnassignedMessageListForPass3[curIndex]; + if ( ( !mi->parent() ) || ( mi->threadingStatus() == MessageItem::ParentMissing ) ) + { + // Parent is missing (either "physically" with the item being not attacched or "logically" + // with the item being attacched to a group or directly to the root. + if ( mi->subjectIsPrefixed() ) + { + // We can try to guess it + MessageItem * mparent = guessMessageParent( mi ); + + if ( mparent ) + { + // imperfect parent found + if ( mi->isViewable() ) + { + // mi was already viewable, we're just trying to re-parent it better... + attachMessageToParent( mparent, mi ); + if ( !mparent->isViewable() ) + { + // re-attach it immediately (so current item is not lost) + MessageItem * topmost = mparent->topmostMessage(); + Q_ASSERT( !topmost->parent() ); // groups are always viewable! + topmost->setThreadingStatus( MessageItem::ParentMissing ); + attachMessageToGroupHeader( topmost ); + } + } else { + // mi wasn't viewable yet.. no need to attach parent + attachMessageToParent( mparent, mi ); + } + // and we're done for now + } else { + // so parent not found, (threadingStatus() is either MessageItem::ParentMissing or MessageItem::NonThreadable) + Q_ASSERT( ( mi->threadingStatus() == MessageItem::ParentMissing ) || ( mi->threadingStatus() == MessageItem::NonThreadable ) ); + mUnassignedMessageListForPass4.append( mi ); // this is ~O(1) + // and wait for Pass4 + } + } else { + // can't guess the parent as the subject isn't prefixed + Q_ASSERT( ( mi->threadingStatus() == MessageItem::ParentMissing ) || ( mi->threadingStatus() == MessageItem::NonThreadable ) ); + mUnassignedMessageListForPass4.append( mi ); // this is ~O(1) + // and wait for Pass4 + } } else { - // so parent not found, (threadingStatus() is either MessageItem::ParentMissing or MessageItem::NonThreadable) - Q_ASSERT( ( mi->threadingStatus() == MessageItem::ParentMissing ) || ( mi->threadingStatus() == MessageItem::NonThreadable ) ); - mUnassignedMessageListForPass4.append( mi ); // this is ~O(1) - // and wait for Pass4 - } - } else { - // can't guess the parent as the subject isn't prefixed - Q_ASSERT( ( mi->threadingStatus() == MessageItem::ParentMissing ) || ( mi->threadingStatus() == MessageItem::NonThreadable ) ); - mUnassignedMessageListForPass4.append( mi ); // this is ~O(1) - // and wait for Pass4 - } - } else { - // Has a parent: either perfect parent already found or non threadable. - // Since we don't end here if mi has status of parent missing then mi must not have imperfect parent. - Q_ASSERT( mi->threadingStatus() != MessageItem::ImperfectParentFound ); - Q_ASSERT( mi->isViewable() ); - } + // Has a parent: either perfect parent already found or non threadable. + // Since we don't end here if mi has status of parent missing then mi must not have imperfect parent. + Q_ASSERT( mi->threadingStatus() != MessageItem::ImperfectParentFound ); + Q_ASSERT( mi->isViewable() ); + } - curIndex++; + curIndex++; - // FIXME: In fact a single call to attachMessageToGroupHeader() is likely to manipulate - // a subtree with a LOT of messages inside. If interactivity is favored - // we should check the time really more often. - if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) - { - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - if ( curIndex <= endIndex ) + // FIXME: In fact a single call to attachMessageToGroupHeader() is likely to manipulate + // a subtree with a LOT of messages inside. If interactivity is favored + // we should check the time really more often. + if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) { - job->setCurrentIndex( curIndex ); - return ViewItemJobInterrupted; + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + if ( curIndex <= endIndex ) + { + job->setCurrentIndex( curIndex ); + return ViewItemJobInterrupted; + } + } } - } } - } - mUnassignedMessageListForPass3.clear(); - return ViewItemJobCompleted; + mUnassignedMessageListForPass3.clear(); + return ViewItemJobCompleted; } ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass2( ViewItemJob *job, const QTime &tStart ) { - // In this pass we scan the mUnassignedMessageList and try to do construct the threads. - // If some thread leader message got attacched to the viewable tree in Pass1Fill then - // we'll also attach all of its children too. The thread leaders we were unable - // to attach in Pass1Fill and their children (which we find here) will make it to the small Pass3 - - // We don't shrink the mUnassignedMessageList for two reasons: - // - It would mess up this chunked algorithm by shifting indexes - // - mUnassignedMessageList is a QList which is basically an array. It's faster - // to traverse an array of N entries than to remove K>0 entries one by one and - // to traverse the remaining N-K entries. - - // We call this pass "Threading" - - int elapsed; - - int curIndex = job->currentIndex(); - int endIndex = job->endIndex(); - - while ( curIndex <= endIndex ) - { - // If we're here, then threading is requested for sure. - MessageItem * mi = mUnassignedMessageListForPass2[curIndex]; - // The item may or may not have a parent. - // If it has no parent or it has a temporary one (mi->parent() && mi->threadingStatus() == MessageItem::ParentMissing) - // then we attempt to (re-)thread it. Otherwise we just do nothing (the job has already been done by the previous steps). - if ( ( !mi->parent() ) || ( mi->threadingStatus() == MessageItem::ParentMissing ) ) - { - MessageItem * mparent = findMessageParent( mi ); - - if ( mparent ) - { - // parent found, either perfect or imperfect - if ( mi->isViewable() ) - { - // mi was already viewable, we're just trying to re-parent it better... - attachMessageToParent( mparent, mi ); - if ( !mparent->isViewable() ) - { - // re-attach it immediately (so current item is not lost) - MessageItem * topmost = mparent->topmostMessage(); - Q_ASSERT( !topmost->parent() ); // groups are always viewable! - topmost->setThreadingStatus( MessageItem::ParentMissing ); - attachMessageToGroupHeader( topmost ); - } - } else { - // mi wasn't viewable yet.. no need to attach parent - attachMessageToParent( mparent, mi ); - } - // and we're done for now - } else { - // so parent not found, (threadingStatus() is either MessageItem::ParentMissing or MessageItem::NonThreadable) - switch( mi->threadingStatus() ) + // In this pass we scan the mUnassignedMessageList and try to do construct the threads. + // If some thread leader message got attacched to the viewable tree in Pass1Fill then + // we'll also attach all of its children too. The thread leaders we were unable + // to attach in Pass1Fill and their children (which we find here) will make it to the small Pass3 + + // We don't shrink the mUnassignedMessageList for two reasons: + // - It would mess up this chunked algorithm by shifting indexes + // - mUnassignedMessageList is a QList which is basically an array. It's faster + // to traverse an array of N entries than to remove K>0 entries one by one and + // to traverse the remaining N-K entries. + + // We call this pass "Threading" + + int elapsed; + + int curIndex = job->currentIndex(); + int endIndex = job->endIndex(); + + while ( curIndex <= endIndex ) + { + // If we're here, then threading is requested for sure. + MessageItem * mi = mUnassignedMessageListForPass2[curIndex]; + // The item may or may not have a parent. + // If it has no parent or it has a temporary one (mi->parent() && mi->threadingStatus() == MessageItem::ParentMissing) + // then we attempt to (re-)thread it. Otherwise we just do nothing (the job has already been done by the previous steps). + if ( ( !mi->parent() ) || ( mi->threadingStatus() == MessageItem::ParentMissing ) ) { - case MessageItem::ParentMissing: - if ( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ) + MessageItem * mparent = findMessageParent( mi ); + + if ( mparent ) { - // parent missing but still can be found in Pass3 - mUnassignedMessageListForPass3.append( mi ); // this is ~O(1) + // parent found, either perfect or imperfect + if ( mi->isViewable() ) + { + // mi was already viewable, we're just trying to re-parent it better... + attachMessageToParent( mparent, mi ); + if ( !mparent->isViewable() ) + { + // re-attach it immediately (so current item is not lost) + MessageItem * topmost = mparent->topmostMessage(); + Q_ASSERT( !topmost->parent() ); // groups are always viewable! + topmost->setThreadingStatus( MessageItem::ParentMissing ); + attachMessageToGroupHeader( topmost ); + } + } else { + // mi wasn't viewable yet.. no need to attach parent + attachMessageToParent( mparent, mi ); + } + // and we're done for now } else { - // We're not doing subject based threading: will never be threaded, go straight to Pass4 - mUnassignedMessageListForPass4.append( mi ); // this is ~O(1) + // so parent not found, (threadingStatus() is either MessageItem::ParentMissing or MessageItem::NonThreadable) + switch( mi->threadingStatus() ) + { + case MessageItem::ParentMissing: + if ( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ) + { + // parent missing but still can be found in Pass3 + mUnassignedMessageListForPass3.append( mi ); // this is ~O(1) + } else { + // We're not doing subject based threading: will never be threaded, go straight to Pass4 + mUnassignedMessageListForPass4.append( mi ); // this is ~O(1) + } + break; + case MessageItem::NonThreadable: + // will never be threaded, go straight to Pass4 + mUnassignedMessageListForPass4.append( mi ); // this is ~O(1) + break; + default: + // a bug for sure + kWarning() << "ERROR: Invalid message threading status returned by findMessageParent()!"; + Q_ASSERT( false ); + break; + } + } + } else { + // Has a parent: either perfect parent already found or non threadable. + // Since we don't end here if mi has status of parent missing then mi must not have imperfect parent. + Q_ASSERT( mi->threadingStatus() != MessageItem::ImperfectParentFound ); + if ( !mi->isViewable() ) + { + kWarning() << "Non viewable message " << mi << " subject " << mi->subject().toUtf8().data(); + Q_ASSERT( mi->isViewable() ); } - break; - case MessageItem::NonThreadable: - // will never be threaded, go straight to Pass4 - mUnassignedMessageListForPass4.append( mi ); // this is ~O(1) - break; - default: - // a bug for sure - kWarning() << "ERROR: Invalid message threading status returned by findMessageParent()!"; - Q_ASSERT( false ); - break; } - } - } else { - // Has a parent: either perfect parent already found or non threadable. - // Since we don't end here if mi has status of parent missing then mi must not have imperfect parent. - Q_ASSERT( mi->threadingStatus() != MessageItem::ImperfectParentFound ); - if ( !mi->isViewable() ) - { - kWarning() << "Non viewable message " << mi << " subject " << mi->subject().toUtf8().data(); - Q_ASSERT( mi->isViewable() ); - } - } - curIndex++; + curIndex++; - // FIXME: In fact a single call to attachMessageToGroupHeader() is likely to manipulate - // a subtree with a LOT of messages inside. If interactivity is favored - // we should check the time really more often. - if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) - { - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - if ( curIndex <= endIndex ) + // FIXME: In fact a single call to attachMessageToGroupHeader() is likely to manipulate + // a subtree with a LOT of messages inside. If interactivity is favored + // we should check the time really more often. + if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) { - job->setCurrentIndex( curIndex ); - return ViewItemJobInterrupted; + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + if ( curIndex <= endIndex ) + { + job->setCurrentIndex( curIndex ); + return ViewItemJobInterrupted; + } + } } - } } - } - mUnassignedMessageListForPass2.clear(); - return ViewItemJobCompleted; + mUnassignedMessageListForPass2.clear(); + return ViewItemJobCompleted; } ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass1Fill( ViewItemJob *job, const QTime &tStart ) { - // In this pass we scan the a contiguous region of the underlying storage (that is - // assumed to be FLAT) and create the corresponding MessageItem objects. - // The deal is to show items to the user as soon as possible so in this pass we - // *TRY* to attach them to the viewable tree (which is rooted on mRootItem). - // Messages we're unable to attach for some reason (mainly due to threading) get appended - // to mUnassignedMessageList and wait for Pass2. + // In this pass we scan the a contiguous region of the underlying storage (that is + // assumed to be FLAT) and create the corresponding MessageItem objects. + // The deal is to show items to the user as soon as possible so in this pass we + // *TRY* to attach them to the viewable tree (which is rooted on mRootItem). + // Messages we're unable to attach for some reason (mainly due to threading) get appended + // to mUnassignedMessageList and wait for Pass2. - // We call this pass "Processing" + // We call this pass "Processing" - int elapsed; + int elapsed; - // Should we use the receiver or the sender field for sorting ? - bool bUseReceiver = mStorageModelContainsOutboundMessages; + // Should we use the receiver or the sender field for sorting ? + bool bUseReceiver = mStorageModelContainsOutboundMessages; - // The begin storage index of our work - int curIndex = job->currentIndex(); - // The end storage index of our work. - int endIndex = job->endIndex(); + // The begin storage index of our work + int curIndex = job->currentIndex(); + // The end storage index of our work. + int endIndex = job->endIndex(); - unsigned long msgToSelect = mPreSelectionMode == PreSelectLastSelected ? mStorageModel->preSelectedMessage() : 0; + unsigned long msgToSelect = mPreSelectionMode == PreSelectLastSelected ? mStorageModel->preSelectedMessage() : 0; - MessageItem * mi = 0; + MessageItem * mi = 0; - while( curIndex <= endIndex ) - { - // Create the message item with no parent: we'll set it later - if ( !mi ) + while( curIndex <= endIndex ) { - mi = new MessageItem(); - } else { - // a MessageItem discarded by a previous iteration: reuse it. - Q_ASSERT( mi->parent() == 0 ); - } - - if ( !mStorageModel->initializeMessageItem( mi, curIndex, bUseReceiver ) ) - { - // ugh - kWarning() << "Fill of the MessageItem at storage row index " << curIndex << " failed"; - curIndex++; - continue; - } + // Create the message item with no parent: we'll set it later + if ( !mi ) + { + mi = new MessageItem(); + } else { + // a MessageItem discarded by a previous iteration: reuse it. + Q_ASSERT( mi->parent() == 0 ); + } - // If we're supposed to pre-select a specific message, check if it's this one. - if ( msgToSelect != 0 && msgToSelect == mi->uniqueId() ) { - // Found, it's this one. - // But actually it's not viewable (so not selectable). We must wait - // until the end of the job to be 100% sure. So here we just translate - // the unique id to a MessageItem pointer and wait. - mLastSelectedMessageInFolder = mi; - msgToSelect = 0; // already found, don't bother checking anymore - } + if ( !mStorageModel->initializeMessageItem( mi, curIndex, bUseReceiver ) ) + { + // ugh + kWarning() << "Fill of the MessageItem at storage row index " << curIndex << " failed"; + curIndex++; + continue; + } - // Update the newest/oldest message, since we might be supposed to select those later - if ( !mOldestItem || mOldestItem->date() > mi->date() ) { - mOldestItem = mi; - } - if ( !mNewestItem || mNewestItem->date() < mi->date() ) { - mNewestItem = mi; - } + // If we're supposed to pre-select a specific message, check if it's this one. + if ( msgToSelect != 0 && msgToSelect == mi->uniqueId() ) { + // Found, it's this one. + // But actually it's not viewable (so not selectable). We must wait + // until the end of the job to be 100% sure. So here we just translate + // the unique id to a MessageItem pointer and wait. + mLastSelectedMessageInFolder = mi; + msgToSelect = 0; // already found, don't bother checking anymore + } - // Ok.. it passed the initial checks: we will not be discarding it. - // Make this message item an invariant index to the underlying model storage. - mInvariantRowMapper->createModelInvariantIndex( curIndex, mi ); + // Update the newest/oldest message, since we might be supposed to select those later + if ( !mOldestItem || mOldestItem->date() > mi->date() ) { + mOldestItem = mi; + } + if ( !mNewestItem || mNewestItem->date() < mi->date() ) { + mNewestItem = mi; + } + // Ok.. it passed the initial checks: we will not be discarding it. + // Make this message item an invariant index to the underlying model storage. + mInvariantRowMapper->createModelInvariantIndex( curIndex, mi ); - // Attempt to do threading as soon as possible (to display items to the user) - if ( mAggregation->threading() != Aggregation::NoThreading ) - { - // Threading is requested - // Fetch the data needed for proper threading - // Add the item to the threading caches + // Attempt to do threading as soon as possible (to display items to the user) + if ( mAggregation->threading() != Aggregation::NoThreading ) + { + // Threading is requested - switch( mAggregation->threading() ) - { - case Aggregation::PerfectReferencesAndSubject: - mStorageModel->fillMessageItemThreadingData( mi, curIndex, StorageModel::PerfectThreadingReferencesAndSubject ); + // Fetch the data needed for proper threading + // Add the item to the threading caches - // We also need to build the subject-based threading cache - addMessageToSubjectBasedThreadingCache( mi ); - break; - case Aggregation::PerfectAndReferences: - mStorageModel->fillMessageItemThreadingData( mi, curIndex, StorageModel::PerfectThreadingPlusReferences ); - break; - default: - mStorageModel->fillMessageItemThreadingData( mi, curIndex, StorageModel::PerfectThreadingOnly ); - break; - } + switch( mAggregation->threading() ) + { + case Aggregation::PerfectReferencesAndSubject: + mStorageModel->fillMessageItemThreadingData( mi, curIndex, StorageModel::PerfectThreadingReferencesAndSubject ); - // Perfect/References threading cache - mThreadingCacheMessageIdMD5ToMessageItem.insert( mi->messageIdMD5(), mi ); + // We also need to build the subject-based threading cache + addMessageToSubjectBasedThreadingCache( mi ); + break; + case Aggregation::PerfectAndReferences: + mStorageModel->fillMessageItemThreadingData( mi, curIndex, StorageModel::PerfectThreadingPlusReferences ); + break; + default: + mStorageModel->fillMessageItemThreadingData( mi, curIndex, StorageModel::PerfectThreadingOnly ); + break; + } - // Check if this item is a perfect parent for some imperfectly threaded - // message (that is actually attacched to it, but not necessairly to the - // viewable root). If it is, then remove the imperfect child from its - // current parent rebuild the hierarchy on the fly. + // Perfect/References threading cache + mThreadingCacheMessageIdMD5ToMessageItem.insert( mi->messageIdMD5(), mi ); - bool needsImmediateReAttach = false; + // Check if this item is a perfect parent for some imperfectly threaded + // message (that is actually attacched to it, but not necessairly to the + // viewable root). If it is, then remove the imperfect child from its + // current parent rebuild the hierarchy on the fly. - if ( mThreadingCacheMessageInReplyToIdMD5ToMessageItem.count() > 0 ) // unlikely - { - QList< MessageItem * > lImperfectlyThreaded = mThreadingCacheMessageInReplyToIdMD5ToMessageItem.values( mi->messageIdMD5() ); - if ( !lImperfectlyThreaded.isEmpty() ) - { - // must move all of the items in the perfect parent - QList< MessageItem * >::ConstIterator end( lImperfectlyThreaded.constEnd() ); - for ( QList< MessageItem * >::ConstIterator it = lImperfectlyThreaded.constBegin(); it != end; ++it ) - { - Q_ASSERT( ( *it )->parent() ); - Q_ASSERT( ( *it )->parent() != mi ); + bool needsImmediateReAttach = false; - if ( !( ( (*it)->threadingStatus() == MessageItem::ImperfectParentFound ) || - ( (*it)->threadingStatus() == MessageItem::ParentMissing ) ) ) { - kError() << "Got message " << (*it) << " with threading status" << (*it)->threadingStatus(); - Q_ASSERT_X( false, "ModelPrivate::viewItemJobStepInternalForJobPass1Fill", "Wrong threading status" ); + if ( mThreadingCacheMessageInReplyToIdMD5ToMessageItem.count() > 0 ) // unlikely + { + QList< MessageItem * > lImperfectlyThreaded = mThreadingCacheMessageInReplyToIdMD5ToMessageItem.values( mi->messageIdMD5() ); + if ( !lImperfectlyThreaded.isEmpty() ) + { + // must move all of the items in the perfect parent + QList< MessageItem * >::ConstIterator end( lImperfectlyThreaded.constEnd() ); + for ( QList< MessageItem * >::ConstIterator it = lImperfectlyThreaded.constBegin(); it != end; ++it ) + { + Q_ASSERT( ( *it )->parent() ); + Q_ASSERT( ( *it )->parent() != mi ); + + if ( !( ( (*it)->threadingStatus() == MessageItem::ImperfectParentFound ) || + ( (*it)->threadingStatus() == MessageItem::ParentMissing ) ) ) { + kError() << "Got message " << (*it) << " with threading status" << (*it)->threadingStatus(); + Q_ASSERT_X( false, "ModelPrivate::viewItemJobStepInternalForJobPass1Fill", "Wrong threading status" ); + } + + // If the item was already attached to the view then + // re-attach it immediately. This will avoid a message + // being displayed for a short while in the view and then + // disappear until a perfect parent isn't found. + if ( ( *it )->isViewable() ) + needsImmediateReAttach = true; + + ( *it )->setThreadingStatus( MessageItem::PerfectParentFound ); + attachMessageToParent( mi, *it ); + } + } } - // If the item was already attached to the view then - // re-attach it immediately. This will avoid a message - // being displayed for a short while in the view and then - // disappear until a perfect parent isn't found. - if ( ( *it )->isViewable() ) - needsImmediateReAttach = true; + // FIXME: Might look by "References" too, here... (?) - ( *it )->setThreadingStatus( MessageItem::PerfectParentFound ); - attachMessageToParent( mi, *it ); - } - } - } + // Attempt to do threading with anything we already have in caches until now + // Note that this is likely to work since thread-parent messages tend + // to come before thread-children messages in the folders (simply because of + // date of arrival). - // FIXME: Might look by "References" too, here... (?) + Item * pParent; - // Attempt to do threading with anything we already have in caches until now - // Note that this is likely to work since thread-parent messages tend - // to come before thread-children messages in the folders (simply because of - // date of arrival). + // First of all try to find a "perfect parent", that is the message for that + // we have the ID in the "In-Reply-To" field. This is actually done by using + // MD5 caches of the message ids because of speed. Collisions are very unlikely. - Item * pParent; + const QByteArray md5 = mi->inReplyToIdMD5(); - // First of all try to find a "perfect parent", that is the message for that - // we have the ID in the "In-Reply-To" field. This is actually done by using - // MD5 caches of the message ids because of speed. Collisions are very unlikely. + if ( !md5.isEmpty() ) + { + // Have an In-Reply-To field MD5. + // In well behaved mailing lists 70% of the threadable messages get a parent here :) + pParent = mThreadingCacheMessageIdMD5ToMessageItem.value( md5, 0 ); + + if( pParent ) // very likely + { + // Take care of self-referencing (which is always possible) + // and circular In-Reply-To reference loops which are possible + // in case this item was found to be a perfect parent for some + // imperfectly threaded message just above. + if ( + ( mi == pParent ) || // self referencing message + ( + ( mi->childItemCount() > 0 ) && // mi already has children, this is fast to determine + pParent->hasAncestor( mi ) // pParent is in the mi's children tree + ) + ) + { + // Bad, bad message.. it has In-Reply-To equal to Message-Id + // or it's in a circular In-Reply-To reference loop. + // Will wait for Pass2 with References-Id only + kWarning() << "Circular In-Reply-To reference loop detected in the message tree"; + mUnassignedMessageListForPass2.append( mi ); + } else { + // wow, got a perfect parent for this message! + mi->setThreadingStatus( MessageItem::PerfectParentFound ); + attachMessageToParent( pParent, mi ); + // we're done with this message (also for Pass2) + } + } else { + // got no parent + // will have to wait Pass2 + mUnassignedMessageListForPass2.append( mi ); + } + } else { + // No In-Reply-To header. - const QByteArray md5 = mi->inReplyToIdMD5(); + bool mightHaveOtherMeansForThreading; - if ( !md5.isEmpty() ) - { - // Have an In-Reply-To field MD5. - // In well behaved mailing lists 70% of the threadable messages get a parent here :) - pParent = mThreadingCacheMessageIdMD5ToMessageItem.value( md5, 0 ); + switch( mAggregation->threading() ) + { + case Aggregation::PerfectReferencesAndSubject: + mightHaveOtherMeansForThreading = mi->subjectIsPrefixed() || !mi->referencesIdMD5().isEmpty(); + break; + case Aggregation::PerfectAndReferences: + mightHaveOtherMeansForThreading = !mi->referencesIdMD5().isEmpty(); + break; + case Aggregation::PerfectOnly: + mightHaveOtherMeansForThreading = false; + break; + default: + // BUG: there shouldn't be other values (NoThreading is excluded in an upper branch) + Q_ASSERT( false ); + mightHaveOtherMeansForThreading = false; // make gcc happy + break; + } + + if ( mightHaveOtherMeansForThreading ) + { + // We might have other means for threading this message, wait until Pass2 + mUnassignedMessageListForPass2.append( mi ); + } else { + // No other means for threading this message. This is either + // a standalone message or a thread leader. + // If there is no grouping in effect or thread leaders are just the "topmost" + // messages then we might be done with this one. + if ( + ( mAggregation->grouping() == Aggregation::NoGrouping ) || + ( mAggregation->threadLeader() == Aggregation::TopmostMessage ) + ) + { + // We're done with this message: it will be surely either toplevel (no grouping in effect) + // or a thread leader with a well defined group. Do it :) + //kDebug() << "Setting message status from " << mi->threadingStatus() << " to non threadable (1) " << mi; + mi->setThreadingStatus( MessageItem::NonThreadable ); + // Locate the parent group for this item + attachMessageToGroupHeader( mi ); + // we're done with this message (also for Pass2) + } else { + // Threads belong to the most recent message in the thread. This means + // that we have to wait until Pass2 or Pass3 to assign a group. + mUnassignedMessageListForPass2.append( mi ); + } + } + } - if( pParent ) // very likely - { - // Take care of self-referencing (which is always possible) - // and circular In-Reply-To reference loops which are possible - // in case this item was found to be a perfect parent for some - // imperfectly threaded message just above. - if ( - ( mi == pParent ) || // self referencing message - ( - ( mi->childItemCount() > 0 ) && // mi already has children, this is fast to determine - pParent->hasAncestor( mi ) // pParent is in the mi's children tree - ) - ) - { - // Bad, bad message.. it has In-Reply-To equal to Message-Id - // or it's in a circular In-Reply-To reference loop. - // Will wait for Pass2 with References-Id only - kWarning() << "Circular In-Reply-To reference loop detected in the message tree"; - mUnassignedMessageListForPass2.append( mi ); - } else { - // wow, got a perfect parent for this message! - mi->setThreadingStatus( MessageItem::PerfectParentFound ); - attachMessageToParent( pParent, mi ); - // we're done with this message (also for Pass2) - } - } else { - // got no parent - // will have to wait Pass2 - mUnassignedMessageListForPass2.append( mi ); - } - } else { - // No In-Reply-To header. - - bool mightHaveOtherMeansForThreading; - - switch( mAggregation->threading() ) - { - case Aggregation::PerfectReferencesAndSubject: - mightHaveOtherMeansForThreading = mi->subjectIsPrefixed() || !mi->referencesIdMD5().isEmpty(); - break; - case Aggregation::PerfectAndReferences: - mightHaveOtherMeansForThreading = !mi->referencesIdMD5().isEmpty(); - break; - case Aggregation::PerfectOnly: - mightHaveOtherMeansForThreading = false; - break; - default: - // BUG: there shouldn't be other values (NoThreading is excluded in an upper branch) - Q_ASSERT( false ); - mightHaveOtherMeansForThreading = false; // make gcc happy - break; - } + if ( needsImmediateReAttach && !mi->isViewable() ) + { + // The item gathered previously viewable children. They must be immediately + // re-shown. So this item must currently be attached to the view. + // This is a temporary measure: it will be probably still moved. + MessageItem * topmost = mi->topmostMessage(); + Q_ASSERT( topmost->threadingStatus() == MessageItem::ParentMissing ); + attachMessageToGroupHeader( topmost ); + } - if ( mightHaveOtherMeansForThreading ) - { - // We might have other means for threading this message, wait until Pass2 - mUnassignedMessageListForPass2.append( mi ); } else { - // No other means for threading this message. This is either - // a standalone message or a thread leader. - // If there is no grouping in effect or thread leaders are just the "topmost" - // messages then we might be done with this one. - if ( - ( mAggregation->grouping() == Aggregation::NoGrouping ) || - ( mAggregation->threadLeader() == Aggregation::TopmostMessage ) - ) - { - // We're done with this message: it will be surely either toplevel (no grouping in effect) - // or a thread leader with a well defined group. Do it :) - //kDebug() << "Setting message status from " << mi->threadingStatus() << " to non threadable (1) " << mi; + // else no threading requested: we don't even need Pass2 + // set not threadable status (even if it might be not true, but in this mode we don't care) + //kDebug() << "Setting message status from " << mi->threadingStatus() << " to non threadable (2) " << mi; mi->setThreadingStatus( MessageItem::NonThreadable ); - // Locate the parent group for this item - attachMessageToGroupHeader( mi ); + // locate the parent group for this item + if ( mAggregation->grouping() == Aggregation::NoGrouping ) + attachMessageToParent( mRootItem, mi ); // no groups requested, attach directly to root + else + attachMessageToGroupHeader( mi ); // we're done with this message (also for Pass2) - } else { - // Threads belong to the most recent message in the thread. This means - // that we have to wait until Pass2 or Pass3 to assign a group. - mUnassignedMessageListForPass2.append( mi ); - } - } - } - - if ( needsImmediateReAttach && !mi->isViewable() ) - { - // The item gathered previously viewable children. They must be immediately - // re-shown. So this item must currently be attached to the view. - // This is a temporary measure: it will be probably still moved. - MessageItem * topmost = mi->topmostMessage(); - Q_ASSERT( topmost->threadingStatus() == MessageItem::ParentMissing ); - attachMessageToGroupHeader( topmost ); - } - - } else { - // else no threading requested: we don't even need Pass2 - // set not threadable status (even if it might be not true, but in this mode we don't care) - //kDebug() << "Setting message status from " << mi->threadingStatus() << " to non threadable (2) " << mi; - mi->setThreadingStatus( MessageItem::NonThreadable ); - // locate the parent group for this item - if ( mAggregation->grouping() == Aggregation::NoGrouping ) - attachMessageToParent( mRootItem, mi ); // no groups requested, attach directly to root - else - attachMessageToGroupHeader( mi ); - // we're done with this message (also for Pass2) - } - - mi = 0; // this item was pushed somewhere, create a new one at next iteration - curIndex++; - - if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) - { - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - if ( curIndex <= endIndex ) - { - job->setCurrentIndex( curIndex ); - return ViewItemJobInterrupted; - } - } - } - } - - if ( mi ) - delete mi; - return ViewItemJobCompleted; -} - -ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass1Cleanup( ViewItemJob *job, const QTime &tStart ) -{ - Q_ASSERT( mModelForItemFunctions ); // UI must be not disconnected here - // In this pass we remove the MessageItem objects that are present in the job - // and put their children in the unassigned message list. - - // Note that this list in fact contains MessageItem objects (we need dynamic_cast<>). - QList< ModelInvariantIndex * > * invalidatedMessages = job->invariantIndexList(); - - // We don't shrink the invalidatedMessages because it's basically an array. - // It's faster to traverse an array of N entries than to remove K>0 entries - // one by one and to traverse the remaining N-K entries. - - int elapsed; - - // The begin index of our work - int curIndex = job->currentIndex(); - // The end index of our work. - int endIndex = job->endIndex(); - - if ( curIndex == job->startIndex() ) - Q_ASSERT( mOrphanChildrenHash.isEmpty() ); - - while( curIndex <= endIndex ) - { - // Get the underlying storage message data... - MessageItem * dyingMessage = dynamic_cast< MessageItem * >( invalidatedMessages->at( curIndex ) ); - // This MUST NOT be null (otherwise we have a bug somewhere in this file). - Q_ASSERT( dyingMessage ); + } - // If we were going to pre-select this message but we were interrupted - // *before* it was actually made viewable, we just clear the pre-selection pointer - // and unique id (abort pre-selection). - if ( dyingMessage == mLastSelectedMessageInFolder ) - { - mLastSelectedMessageInFolder = 0; - mPreSelectionMode = PreSelectNone; - } + mi = 0; // this item was pushed somewhere, create a new one at next iteration + curIndex++; - // remove the message from any pending user job - if ( mPersistentSetManager ) - { - mPersistentSetManager->removeMessageItemFromAllSets( dyingMessage ); - if ( mPersistentSetManager->setCount() < 1 ) - { - delete mPersistentSetManager; - mPersistentSetManager = 0; - } + if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) + { + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + if ( curIndex <= endIndex ) + { + job->setCurrentIndex( curIndex ); + return ViewItemJobInterrupted; + } + } + } } - if ( dyingMessage->parent() ) - { - // Handle saving the current selection: if this item was the current before the step - // then zero it out. We have killed it and it's OK for the current item to change. - - if ( dyingMessage == mCurrentItemToRestoreAfterViewItemJobStep ) - { - Q_ASSERT( dyingMessage->isViewable() ); - // Try to select the item below the removed one as it helps in doing a "readon" of emails: - // you read a message, decide to delete it and then go to the next. - // Qt tends to select the message above the removed one instead (this is a hardcoded logic in - // QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved()). - mCurrentItemToRestoreAfterViewItemJobStep = mView->messageItemAfter( dyingMessage, MessageTypeAny, false ); + if ( mi ) + delete mi; + return ViewItemJobCompleted; +} - if ( !mCurrentItemToRestoreAfterViewItemJobStep ) +ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass1Cleanup( ViewItemJob *job, const QTime &tStart ) +{ + Q_ASSERT( mModelForItemFunctions ); // UI must be not disconnected here + // In this pass we remove the MessageItem objects that are present in the job + // and put their children in the unassigned message list. + + // Note that this list in fact contains MessageItem objects (we need dynamic_cast<>). + QList< ModelInvariantIndex * > * invalidatedMessages = job->invariantIndexList(); + + // We don't shrink the invalidatedMessages because it's basically an array. + // It's faster to traverse an array of N entries than to remove K>0 entries + // one by one and to traverse the remaining N-K entries. + + int elapsed; + + // The begin index of our work + int curIndex = job->currentIndex(); + // The end index of our work. + int endIndex = job->endIndex(); + + if ( curIndex == job->startIndex() ) + Q_ASSERT( mOrphanChildrenHash.isEmpty() ); + + while( curIndex <= endIndex ) + { + // Get the underlying storage message data... + MessageItem * dyingMessage = dynamic_cast< MessageItem * >( invalidatedMessages->at( curIndex ) ); + // This MUST NOT be null (otherwise we have a bug somewhere in this file). + Q_ASSERT( dyingMessage ); + + // If we were going to pre-select this message but we were interrupted + // *before* it was actually made viewable, we just clear the pre-selection pointer + // and unique id (abort pre-selection). + if ( dyingMessage == mLastSelectedMessageInFolder ) { - // There is no item below. Try the item above. - // We still do it better than qt which tends to find the *thread* above - // instead of the item above. - mCurrentItemToRestoreAfterViewItemJobStep = mView->messageItemBefore( dyingMessage, MessageTypeAny, false ); + mLastSelectedMessageInFolder = 0; + mPreSelectionMode = PreSelectNone; } - Q_ASSERT( (!mCurrentItemToRestoreAfterViewItemJobStep) || mCurrentItemToRestoreAfterViewItemJobStep->isViewable() ); - } - - if ( - dyingMessage->isViewable() && - ( ( dyingMessage )->childItemCount() > 0 ) && // has children - mView->isExpanded( q->index( dyingMessage, 0 ) ) // is actually expanded - ) - saveExpandedStateOfSubtree( dyingMessage ); + // remove the message from any pending user job + if ( mPersistentSetManager ) + { + mPersistentSetManager->removeMessageItemFromAllSets( dyingMessage ); + if ( mPersistentSetManager->setCount() < 1 ) + { + delete mPersistentSetManager; + mPersistentSetManager = 0; + } + } - Item * oldParent = dyingMessage->parent(); - oldParent->takeChildItem( q, dyingMessage ); + if ( dyingMessage->parent() ) + { + // Handle saving the current selection: if this item was the current before the step + // then zero it out. We have killed it and it's OK for the current item to change. - // FIXME: This can generate many message movements.. it would be nicer - // to start from messages that are higher in the hierarchy so - // we would need to move less stuff above. + if ( dyingMessage == mCurrentItemToRestoreAfterViewItemJobStep ) + { + Q_ASSERT( dyingMessage->isViewable() ); + // Try to select the item below the removed one as it helps in doing a "readon" of emails: + // you read a message, decide to delete it and then go to the next. + // Qt tends to select the message above the removed one instead (this is a hardcoded logic in + // QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved()). + mCurrentItemToRestoreAfterViewItemJobStep = mView->messageItemAfter( dyingMessage, MessageTypeAny, false ); + + if ( !mCurrentItemToRestoreAfterViewItemJobStep ) + { + // There is no item below. Try the item above. + // We still do it better than qt which tends to find the *thread* above + // instead of the item above. + mCurrentItemToRestoreAfterViewItemJobStep = mView->messageItemBefore( dyingMessage, MessageTypeAny, false ); + } - if ( oldParent != mRootItem ) - messageDetachedUpdateParentProperties( oldParent, dyingMessage ); + Q_ASSERT( (!mCurrentItemToRestoreAfterViewItemJobStep) || mCurrentItemToRestoreAfterViewItemJobStep->isViewable() ); + } - // We might have already removed its parent from the view, so it - // might already be in the orphan child hash... - if ( dyingMessage->threadingStatus() == MessageItem::ParentMissing ) - mOrphanChildrenHash.remove( dyingMessage ); // this can turn to a no-op (dyingMessage not present in fact) + if ( + dyingMessage->isViewable() && + ( ( dyingMessage )->childItemCount() > 0 ) && // has children + mView->isExpanded( q->index( dyingMessage, 0 ) ) // is actually expanded + ) + saveExpandedStateOfSubtree( dyingMessage ); + + Item * oldParent = dyingMessage->parent(); + oldParent->takeChildItem( q, dyingMessage ); + + // FIXME: This can generate many message movements.. it would be nicer + // to start from messages that are higher in the hierarchy so + // we would need to move less stuff above. + + if ( oldParent != mRootItem ) + messageDetachedUpdateParentProperties( oldParent, dyingMessage ); + + // We might have already removed its parent from the view, so it + // might already be in the orphan child hash... + if ( dyingMessage->threadingStatus() == MessageItem::ParentMissing ) + mOrphanChildrenHash.remove( dyingMessage ); // this can turn to a no-op (dyingMessage not present in fact) - } else { - // The dying message had no parent: this should happen only if it's already an orphan + } else { + // The dying message had no parent: this should happen only if it's already an orphan - Q_ASSERT( dyingMessage->threadingStatus() == MessageItem::ParentMissing ); - Q_ASSERT( mOrphanChildrenHash.contains( dyingMessage ) ); - Q_ASSERT( dyingMessage != mCurrentItemToRestoreAfterViewItemJobStep ); + Q_ASSERT( dyingMessage->threadingStatus() == MessageItem::ParentMissing ); + Q_ASSERT( mOrphanChildrenHash.contains( dyingMessage ) ); + Q_ASSERT( dyingMessage != mCurrentItemToRestoreAfterViewItemJobStep ); - mOrphanChildrenHash.remove( dyingMessage ); - } + mOrphanChildrenHash.remove( dyingMessage ); + } - if ( mAggregation->threading() != Aggregation::NoThreading ) - { - // Threading is requested: remove the message from threading caches. + if ( mAggregation->threading() != Aggregation::NoThreading ) + { + // Threading is requested: remove the message from threading caches. - // Remove from the cache of potential parent items - mThreadingCacheMessageIdMD5ToMessageItem.remove( dyingMessage->messageIdMD5() ); + // Remove from the cache of potential parent items + mThreadingCacheMessageIdMD5ToMessageItem.remove( dyingMessage->messageIdMD5() ); - // If we also have a cache for subject-based threading then remove the message from there too - if( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ) - removeMessageFromSubjectBasedThreadingCache( dyingMessage ); + // If we also have a cache for subject-based threading then remove the message from there too + if( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ) + removeMessageFromSubjectBasedThreadingCache( dyingMessage ); - // If this message wasn't perfectly parented then it might still be in another cache. - switch( dyingMessage->threadingStatus() ) - { - case MessageItem::ImperfectParentFound: - case MessageItem::ParentMissing: - if ( !dyingMessage->inReplyToIdMD5().isEmpty() ) - mThreadingCacheMessageInReplyToIdMD5ToMessageItem.remove( dyingMessage->inReplyToIdMD5() ); - break; - default: - Q_ASSERT( !mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains( dyingMessage->inReplyToIdMD5(), dyingMessage ) ); - // make gcc happy - break; - } - } + // If this message wasn't perfectly parented then it might still be in another cache. + switch( dyingMessage->threadingStatus() ) + { + case MessageItem::ImperfectParentFound: + case MessageItem::ParentMissing: + if ( !dyingMessage->inReplyToIdMD5().isEmpty() ) + mThreadingCacheMessageInReplyToIdMD5ToMessageItem.remove( dyingMessage->inReplyToIdMD5() ); + break; + default: + Q_ASSERT( !mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains( dyingMessage->inReplyToIdMD5(), dyingMessage ) ); + // make gcc happy + break; + } + } - while ( Item * childItem = dyingMessage->firstChildItem() ) - { - MessageItem * childMessage = dynamic_cast< MessageItem * >( childItem ); - Q_ASSERT( childMessage ); + while ( Item * childItem = dyingMessage->firstChildItem() ) + { + MessageItem * childMessage = dynamic_cast< MessageItem * >( childItem ); + Q_ASSERT( childMessage ); - dyingMessage->takeChildItem( q, childMessage ); + dyingMessage->takeChildItem( q, childMessage ); - if ( mAggregation->threading() != Aggregation::NoThreading ) - { - if ( childMessage->threadingStatus() == MessageItem::PerfectParentFound ) - { - // If the child message was perfectly parented then now it had - // lost its perfect parent. Add to the cache of imperfectly parented. - if ( !childMessage->inReplyToIdMD5().isEmpty() ) - { - Q_ASSERT( !mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains( childMessage->inReplyToIdMD5(), childMessage ) ); - mThreadingCacheMessageInReplyToIdMD5ToMessageItem.insert( childMessage->inReplyToIdMD5(), childMessage ); - } - } - } + if ( mAggregation->threading() != Aggregation::NoThreading ) + { + if ( childMessage->threadingStatus() == MessageItem::PerfectParentFound ) + { + // If the child message was perfectly parented then now it had + // lost its perfect parent. Add to the cache of imperfectly parented. + if ( !childMessage->inReplyToIdMD5().isEmpty() ) + { + Q_ASSERT( !mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains( childMessage->inReplyToIdMD5(), childMessage ) ); + mThreadingCacheMessageInReplyToIdMD5ToMessageItem.insert( childMessage->inReplyToIdMD5(), childMessage ); + } + } + } - // Parent is gone - childMessage->setThreadingStatus( MessageItem::ParentMissing ); + // Parent is gone + childMessage->setThreadingStatus( MessageItem::ParentMissing ); - // If the child (or any message in its subtree) is going to be selected, - // then we must immediately reattach it to a temporary group in order for the - // selection to be preserved across multiple steps. Otherwise we could end - // with the child-to-be-selected being non viewable at the end - // of the view job step. Attach to a temporary group. - if ( - // child is going to be re-selected - ( childMessage == mCurrentItemToRestoreAfterViewItemJobStep ) || - ( - // there is a message that is going to be re-selected - mCurrentItemToRestoreAfterViewItemJobStep && - // that message is in the childMessage subtree - mCurrentItemToRestoreAfterViewItemJobStep->hasAncestor( childMessage ) - ) - ) - { - attachMessageToGroupHeader( childMessage ); + // If the child (or any message in its subtree) is going to be selected, + // then we must immediately reattach it to a temporary group in order for the + // selection to be preserved across multiple steps. Otherwise we could end + // with the child-to-be-selected being non viewable at the end + // of the view job step. Attach to a temporary group. + if ( + // child is going to be re-selected + ( childMessage == mCurrentItemToRestoreAfterViewItemJobStep ) || + ( + // there is a message that is going to be re-selected + mCurrentItemToRestoreAfterViewItemJobStep && + // that message is in the childMessage subtree + mCurrentItemToRestoreAfterViewItemJobStep->hasAncestor( childMessage ) + ) + ) + { + attachMessageToGroupHeader( childMessage ); - Q_ASSERT( childMessage->isViewable() ); - } + Q_ASSERT( childMessage->isViewable() ); + } - mOrphanChildrenHash.insert( childMessage, childMessage ); - } + mOrphanChildrenHash.insert( childMessage, childMessage ); + } - if ( mNewestItem == dyingMessage ) { - mNewestItem = 0; - } - if ( mOldestItem == dyingMessage ) { - mOldestItem = 0; - } + if ( mNewestItem == dyingMessage ) { + mNewestItem = 0; + } + if ( mOldestItem == dyingMessage ) { + mOldestItem = 0; + } - delete dyingMessage; + delete dyingMessage; - curIndex++; + curIndex++; - // FIXME: Maybe we should check smaller steps here since the - // code above can generate large message tree movements - // for each single item we sweep in the invalidatedMessages list. - if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) - { - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - if ( curIndex <= endIndex ) + // FIXME: Maybe we should check smaller steps here since the + // code above can generate large message tree movements + // for each single item we sweep in the invalidatedMessages list. + if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) { - job->setCurrentIndex( curIndex ); - return ViewItemJobInterrupted; + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + if ( curIndex <= endIndex ) + { + job->setCurrentIndex( curIndex ); + return ViewItemJobInterrupted; + } + } } - } } - } - // We looped over the entire deleted message list. + // We looped over the entire deleted message list. - job->setCurrentIndex( endIndex + 1 ); + job->setCurrentIndex( endIndex + 1 ); - // A quick last cleaning pass: this is usually very fast so we don't have a real - // Pass enumeration for it. We just include it as trailer of Pass1Cleanup to be executed - // when job->currentIndex() > job->endIndex(); + // A quick last cleaning pass: this is usually very fast so we don't have a real + // Pass enumeration for it. We just include it as trailer of Pass1Cleanup to be executed + // when job->currentIndex() > job->endIndex(); - // We move all the messages from the orphan child hash to the unassigned message - // list and get them ready for the standard Pass2. + // We move all the messages from the orphan child hash to the unassigned message + // list and get them ready for the standard Pass2. - QHash< MessageItem *, MessageItem * >::Iterator it = mOrphanChildrenHash.begin(); - QHash< MessageItem *, MessageItem * >::Iterator end = mOrphanChildrenHash.end(); + QHash< MessageItem *, MessageItem * >::Iterator it = mOrphanChildrenHash.begin(); + QHash< MessageItem *, MessageItem * >::Iterator end = mOrphanChildrenHash.end(); - curIndex = 0; + curIndex = 0; - while ( it != end ) - { - mUnassignedMessageListForPass2.append( *it ); + while ( it != end ) + { + mUnassignedMessageListForPass2.append( *it ); - it = mOrphanChildrenHash.erase( it ); + it = mOrphanChildrenHash.erase( it ); - // This is still interruptible + // This is still interruptible - curIndex++; + curIndex++; - // FIXME: We could take "larger" steps here - if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) - { - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - if ( it != mOrphanChildrenHash.end() ) - return ViewItemJobInterrupted; - } + // FIXME: We could take "larger" steps here + if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) + { + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + if ( it != mOrphanChildrenHash.end() ) + return ViewItemJobInterrupted; + } + } } - } - return ViewItemJobCompleted; + return ViewItemJobCompleted; } ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass1Update( ViewItemJob *job, const QTime &tStart ) { - Q_ASSERT( mModelForItemFunctions ); // UI must be not disconnected here - - // In this pass we simply update the MessageItem objects that are present in the job. + Q_ASSERT( mModelForItemFunctions ); // UI must be not disconnected here - // Note that this list in fact contains MessageItem objects (we need dynamic_cast<>). - QList< ModelInvariantIndex * > * messagesThatNeedUpdate = job->invariantIndexList(); + // In this pass we simply update the MessageItem objects that are present in the job. - // We don't shrink the messagesThatNeedUpdate because it's basically an array. - // It's faster to traverse an array of N entries than to remove K>0 entries - // one by one and to traverse the remaining N-K entries. + // Note that this list in fact contains MessageItem objects (we need dynamic_cast<>). + QList< ModelInvariantIndex * > * messagesThatNeedUpdate = job->invariantIndexList(); - int elapsed; + // We don't shrink the messagesThatNeedUpdate because it's basically an array. + // It's faster to traverse an array of N entries than to remove K>0 entries + // one by one and to traverse the remaining N-K entries. - // The begin index of our work - int curIndex = job->currentIndex(); - // The end index of our work. - int endIndex = job->endIndex(); + int elapsed; - while( curIndex <= endIndex ) - { - // Get the underlying storage message data... - MessageItem * message = dynamic_cast< MessageItem * >( messagesThatNeedUpdate->at( curIndex ) ); - // This MUST NOT be null (otherwise we have a bug somewhere in this file). - Q_ASSERT( message ); + // The begin index of our work + int curIndex = job->currentIndex(); + // The end index of our work. + int endIndex = job->endIndex(); - int row = mInvariantRowMapper->modelInvariantIndexToModelIndexRow( message ); - - if ( row < 0 ) + while( curIndex <= endIndex ) { - // Must have been invalidated (so it's basically about to be deleted) - Q_ASSERT( !message->isValid() ); - // Skip it here. - curIndex++; - continue; - } - - time_t prevDate = message->date(); - time_t prevMaxDate = message->maxDate(); - bool toDoStatus = message->status().isToAct(); - bool prevUnreadStatus = !message->status().isRead(); - bool prevImportantStatus = message->status().isImportant(); + // Get the underlying storage message data... + MessageItem * message = dynamic_cast< MessageItem * >( messagesThatNeedUpdate->at( curIndex ) ); + // This MUST NOT be null (otherwise we have a bug somewhere in this file). + Q_ASSERT( message ); - // The subject based threading cache is sorted by date: we must remove - // the item and re-insert it since updateMessageItemData() may change the date too. - if( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ) - removeMessageFromSubjectBasedThreadingCache( message ); + int row = mInvariantRowMapper->modelInvariantIndexToModelIndexRow( message ); - // Do update - mStorageModel->updateMessageItemData( message, row ); - QModelIndex idx = q->index( message, 0 ); - emit q->dataChanged( idx, idx ); - - // Reinsert the item to the cache, if needed - if( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ) - addMessageToSubjectBasedThreadingCache( message ); - - - int propertyChangeMask = 0; - - if ( prevDate != message->date() ) - propertyChangeMask |= DateChanged; - if ( prevMaxDate != message->maxDate() ) - propertyChangeMask |= MaxDateChanged; - if ( toDoStatus != message->status().isToAct() ) - propertyChangeMask |= ActionItemStatusChanged; - if ( prevUnreadStatus != ( !message->status().isRead() ) ) - propertyChangeMask |= UnreadStatusChanged; - if ( prevImportantStatus != ( !message->status().isImportant() ) ) - propertyChangeMask |= ImportantStatusChanged; - - if ( propertyChangeMask ) - { - // Some message data has changed - // now we need to handle the changes that might cause re-grouping/re-sorting - // and propagate them to the parents. - - Item * pParent = message->parent(); - - if ( pParent && ( pParent != mRootItem ) ) - { - // The following function will return true if itemParent may be affected by the change. - // If the itemParent isn't affected, we stop climbing. - if ( handleItemPropertyChanges( propertyChangeMask, pParent, message ) ) + if ( row < 0 ) { - Q_ASSERT( message->parent() ); // handleItemPropertyChanges() must never leave an item detached - - // Note that actually message->parent() may be different than pParent since - // handleItemPropertyChanges() may have re-grouped it. - - // Time to propagate up. - propagateItemPropertiesToParent( message ); + // Must have been invalidated (so it's basically about to be deleted) + Q_ASSERT( !message->isValid() ); + // Skip it here. + curIndex++; + continue; } - } // else there is no parent so the item isn't attached to the view: re-grouping/re-sorting not needed. - } // else message data didn't change an there is nothing interesting to do - - // (re-)apply the filter, if needed - if ( mFilter && message->isViewable() ) - { - // In all the other cases we (re-)apply the filter to the topmost subtree that this message is in. - Item * pTopMostNonRoot = message->topmostNonRoot(); - Q_ASSERT( pTopMostNonRoot ); - Q_ASSERT( pTopMostNonRoot != mRootItem ); - Q_ASSERT( pTopMostNonRoot->parent() == mRootItem ); + time_t prevDate = message->date(); + time_t prevMaxDate = message->maxDate(); + bool toDoStatus = message->status().isToAct(); + bool prevUnreadStatus = !message->status().isRead(); + bool prevImportantStatus = message->status().isImportant(); + + // The subject based threading cache is sorted by date: we must remove + // the item and re-insert it since updateMessageItemData() may change the date too. + if( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ) + removeMessageFromSubjectBasedThreadingCache( message ); + + // Do update + mStorageModel->updateMessageItemData( message, row ); + QModelIndex idx = q->index( message, 0 ); + emit q->dataChanged( idx, idx ); + + // Reinsert the item to the cache, if needed + if( mAggregation->threading() == Aggregation::PerfectReferencesAndSubject ) + addMessageToSubjectBasedThreadingCache( message ); + + + int propertyChangeMask = 0; + + if ( prevDate != message->date() ) + propertyChangeMask |= DateChanged; + if ( prevMaxDate != message->maxDate() ) + propertyChangeMask |= MaxDateChanged; + if ( toDoStatus != message->status().isToAct() ) + propertyChangeMask |= ActionItemStatusChanged; + if ( prevUnreadStatus != ( !message->status().isRead() ) ) + propertyChangeMask |= UnreadStatusChanged; + if ( prevImportantStatus != ( !message->status().isImportant() ) ) + propertyChangeMask |= ImportantStatusChanged; - // FIXME: The call below works, but it's expensive when we are updating - // a lot of items with filtering enabled. This is because the updated - // items are likely to be in the same subtree which we then filter multiple times. - // A point for us is that when filtering there shouldn't be really many - // items in the view so the user isn't going to update a lot of them at once... - // Well... anyway, the alternative would be to write yet another - // specialized routine that would update only the "message" item - // above and climb up eventually hiding parents (without descending the sibling subtrees again). - // If people complain about performance in this particular case I'll consider that solution. - - applyFilterToSubtree( pTopMostNonRoot, QModelIndex() ); + if ( propertyChangeMask ) + { + // Some message data has changed + // now we need to handle the changes that might cause re-grouping/re-sorting + // and propagate them to the parents. - } // otherwise there is no filter or the item isn't viewable: very likely - // left detached while propagating property changes. Will filter it - // on reattach. + Item * pParent = message->parent(); - // Done updating this message + if ( pParent && ( pParent != mRootItem ) ) + { + // The following function will return true if itemParent may be affected by the change. + // If the itemParent isn't affected, we stop climbing. + if ( handleItemPropertyChanges( propertyChangeMask, pParent, message ) ) + { + Q_ASSERT( message->parent() ); // handleItemPropertyChanges() must never leave an item detached + + // Note that actually message->parent() may be different than pParent since + // handleItemPropertyChanges() may have re-grouped it. + + // Time to propagate up. + propagateItemPropertiesToParent( message ); + } + } // else there is no parent so the item isn't attached to the view: re-grouping/re-sorting not needed. + } // else message data didn't change an there is nothing interesting to do - curIndex++; + // (re-)apply the filter, if needed + if ( mFilter && message->isViewable() ) + { + // In all the other cases we (re-)apply the filter to the topmost subtree that this message is in. + Item * pTopMostNonRoot = message->topmostNonRoot(); - // FIXME: Maybe we should check smaller steps here since the - // code above can generate large message tree movements - // for each single item we sweep in the messagesThatNeedUpdate list. - if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) - { - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - if ( curIndex <= endIndex ) + Q_ASSERT( pTopMostNonRoot ); + Q_ASSERT( pTopMostNonRoot != mRootItem ); + Q_ASSERT( pTopMostNonRoot->parent() == mRootItem ); + + // FIXME: The call below works, but it's expensive when we are updating + // a lot of items with filtering enabled. This is because the updated + // items are likely to be in the same subtree which we then filter multiple times. + // A point for us is that when filtering there shouldn't be really many + // items in the view so the user isn't going to update a lot of them at once... + // Well... anyway, the alternative would be to write yet another + // specialized routine that would update only the "message" item + // above and climb up eventually hiding parents (without descending the sibling subtrees again). + // If people complain about performance in this particular case I'll consider that solution. + + applyFilterToSubtree( pTopMostNonRoot, QModelIndex() ); + + } // otherwise there is no filter or the item isn't viewable: very likely + // left detached while propagating property changes. Will filter it + // on reattach. + + // Done updating this message + + curIndex++; + + // FIXME: Maybe we should check smaller steps here since the + // code above can generate large message tree movements + // for each single item we sweep in the messagesThatNeedUpdate list. + if ( ( curIndex % mViewItemJobStepMessageCheckCount ) == 0 ) { - job->setCurrentIndex( curIndex ); - return ViewItemJobInterrupted; + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + if ( curIndex <= endIndex ) + { + job->setCurrentIndex( curIndex ); + return ViewItemJobInterrupted; + } + } } - } } - } - return ViewItemJobCompleted; + return ViewItemJobCompleted; } ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJob( ViewItemJob *job, const QTime &tStart ) { - // This function does a timed chunk of work for a single Fill View job. - // It attempts to process messages until a timeout forces it to return to the caller. + // This function does a timed chunk of work for a single Fill View job. + // It attempts to process messages until a timeout forces it to return to the caller. - // A macro would improve readability here but since this is a good point - // to place debugger breakpoints then we need it explicited. - // A (template) helper would need to pass many parameters and would not be inlined... - - int elapsed; - - if ( job->currentPass() == ViewItemJob::Pass1Fill ) - { - // We're in Pass1Fill of the job. - switch ( viewItemJobStepInternalForJobPass1Fill( job, tStart ) ) - { - case ViewItemJobInterrupted: - // current job interrupted by timeout: propagate status to caller - return ViewItemJobInterrupted; - break; - case ViewItemJobCompleted: - // pass 1 has been completed - // # TODO: Refactor this, make it virtual or whatever, but switch == bad, code duplication etc - job->setCurrentPass( ViewItemJob::Pass2 ); - job->setStartIndex( 0 ); - job->setEndIndex( mUnassignedMessageListForPass2.count() - 1 ); - // take care of small jobs which never timeout by themselves because - // of a small number of messages. At the end of each job check - // the time used and if we're timeoutting and there is another job - // then interrupt. - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - return ViewItemJobInterrupted; - } // else proceed with the next pass - break; - default: - // This is *really* a BUG - kWarning() << "ERROR: returned an invalid result"; - Q_ASSERT( false ); - break; - } - } else if ( job->currentPass() == ViewItemJob::Pass1Cleanup ) - { - // We're in Pass1Cleanup of the job. - switch ( viewItemJobStepInternalForJobPass1Cleanup( job, tStart ) ) - { - case ViewItemJobInterrupted: - // current job interrupted by timeout: propagate status to caller - return ViewItemJobInterrupted; - break; - case ViewItemJobCompleted: - // pass 1 has been completed - job->setCurrentPass( ViewItemJob::Pass2 ); - job->setStartIndex( 0 ); - job->setEndIndex( mUnassignedMessageListForPass2.count() - 1 ); - // take care of small jobs which never timeout by themselves because - // of a small number of messages. At the end of each job check - // the time used and if we're timeoutting and there is another job - // then interrupt. - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - return ViewItemJobInterrupted; - } // else proceed with the next pass - break; - default: - // This is *really* a BUG - kWarning() << "ERROR: returned an invalid result"; - Q_ASSERT( false ); - break; - } - } else if ( job->currentPass() == ViewItemJob::Pass1Update ) - { - // We're in Pass1Update of the job. - switch ( viewItemJobStepInternalForJobPass1Update( job, tStart ) ) - { - case ViewItemJobInterrupted: - // current job interrupted by timeout: propagate status to caller - return ViewItemJobInterrupted; - break; - case ViewItemJobCompleted: - // pass 1 has been completed - // Since Pass2, Pass3 and Pass4 are empty for an Update operation - // we simply skip them. (TODO: Triple-verify this assertion...). - job->setCurrentPass( ViewItemJob::Pass5 ); - job->setStartIndex( 0 ); - job->setEndIndex( mGroupHeadersThatNeedUpdate.count() - 1 ); - // take care of small jobs which never timeout by themselves because - // of a small number of messages. At the end of each job check - // the time used and if we're timeoutting and there is another job - // then interrupt. - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - return ViewItemJobInterrupted; - } // else proceed with the next pass - break; - default: - // This is *really* a BUG - kWarning() << "ERROR: returned an invalid result"; - Q_ASSERT( false ); - break; + // A macro would improve readability here but since this is a good point + // to place debugger breakpoints then we need it explicited. + // A (template) helper would need to pass many parameters and would not be inlined... + + int elapsed; + + if ( job->currentPass() == ViewItemJob::Pass1Fill ) + { + // We're in Pass1Fill of the job. + switch ( viewItemJobStepInternalForJobPass1Fill( job, tStart ) ) + { + case ViewItemJobInterrupted: + // current job interrupted by timeout: propagate status to caller + return ViewItemJobInterrupted; + break; + case ViewItemJobCompleted: + // pass 1 has been completed + // # TODO: Refactor this, make it virtual or whatever, but switch == bad, code duplication etc + job->setCurrentPass( ViewItemJob::Pass2 ); + job->setStartIndex( 0 ); + job->setEndIndex( mUnassignedMessageListForPass2.count() - 1 ); + // take care of small jobs which never timeout by themselves because + // of a small number of messages. At the end of each job check + // the time used and if we're timeoutting and there is another job + // then interrupt. + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + return ViewItemJobInterrupted; + } // else proceed with the next pass + break; + default: + // This is *really* a BUG + kWarning() << "ERROR: returned an invalid result"; + Q_ASSERT( false ); + break; + } + } else if ( job->currentPass() == ViewItemJob::Pass1Cleanup ) + { + // We're in Pass1Cleanup of the job. + switch ( viewItemJobStepInternalForJobPass1Cleanup( job, tStart ) ) + { + case ViewItemJobInterrupted: + // current job interrupted by timeout: propagate status to caller + return ViewItemJobInterrupted; + break; + case ViewItemJobCompleted: + // pass 1 has been completed + job->setCurrentPass( ViewItemJob::Pass2 ); + job->setStartIndex( 0 ); + job->setEndIndex( mUnassignedMessageListForPass2.count() - 1 ); + // take care of small jobs which never timeout by themselves because + // of a small number of messages. At the end of each job check + // the time used and if we're timeoutting and there is another job + // then interrupt. + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + return ViewItemJobInterrupted; + } // else proceed with the next pass + break; + default: + // This is *really* a BUG + kWarning() << "ERROR: returned an invalid result"; + Q_ASSERT( false ); + break; + } + } else if ( job->currentPass() == ViewItemJob::Pass1Update ) + { + // We're in Pass1Update of the job. + switch ( viewItemJobStepInternalForJobPass1Update( job, tStart ) ) + { + case ViewItemJobInterrupted: + // current job interrupted by timeout: propagate status to caller + return ViewItemJobInterrupted; + break; + case ViewItemJobCompleted: + // pass 1 has been completed + // Since Pass2, Pass3 and Pass4 are empty for an Update operation + // we simply skip them. (TODO: Triple-verify this assertion...). + job->setCurrentPass( ViewItemJob::Pass5 ); + job->setStartIndex( 0 ); + job->setEndIndex( mGroupHeadersThatNeedUpdate.count() - 1 ); + // take care of small jobs which never timeout by themselves because + // of a small number of messages. At the end of each job check + // the time used and if we're timeoutting and there is another job + // then interrupt. + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + return ViewItemJobInterrupted; + } // else proceed with the next pass + break; + default: + // This is *really* a BUG + kWarning() << "ERROR: returned an invalid result"; + Q_ASSERT( false ); + break; + } } - } - // Pass1Fill/Pass1Cleanup/Pass1Update has been already completed. + // Pass1Fill/Pass1Cleanup/Pass1Update has been already completed. - if ( job->currentPass() == ViewItemJob::Pass2 ) - { - // We're in Pass2 of the job. - switch ( viewItemJobStepInternalForJobPass2( job, tStart ) ) - { - case ViewItemJobInterrupted: - // current job interrupted by timeout: propagate status to caller - return ViewItemJobInterrupted; - break; - case ViewItemJobCompleted: - // pass 2 has been completed - job->setCurrentPass( ViewItemJob::Pass3 ); - job->setStartIndex( 0 ); - job->setEndIndex( mUnassignedMessageListForPass3.count() - 1 ); - // take care of small jobs which never timeout by themselves because - // of a small number of messages. At the end of each job check - // the time used and if we're timeoutting and there is another job - // then interrupt. - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - return ViewItemJobInterrupted; - // else proceed with the next pass - break; - default: - // This is *really* a BUG - kWarning() << "ERROR: returned an invalid result"; - Q_ASSERT( false ); - break; + if ( job->currentPass() == ViewItemJob::Pass2 ) + { + // We're in Pass2 of the job. + switch ( viewItemJobStepInternalForJobPass2( job, tStart ) ) + { + case ViewItemJobInterrupted: + // current job interrupted by timeout: propagate status to caller + return ViewItemJobInterrupted; + break; + case ViewItemJobCompleted: + // pass 2 has been completed + job->setCurrentPass( ViewItemJob::Pass3 ); + job->setStartIndex( 0 ); + job->setEndIndex( mUnassignedMessageListForPass3.count() - 1 ); + // take care of small jobs which never timeout by themselves because + // of a small number of messages. At the end of each job check + // the time used and if we're timeoutting and there is another job + // then interrupt. + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + return ViewItemJobInterrupted; + // else proceed with the next pass + break; + default: + // This is *really* a BUG + kWarning() << "ERROR: returned an invalid result"; + Q_ASSERT( false ); + break; + } } - } - if ( job->currentPass() == ViewItemJob::Pass3 ) - { - // We're in Pass3 of the job. - switch ( viewItemJobStepInternalForJobPass3( job, tStart ) ) - { - case ViewItemJobInterrupted: - // current job interrupted by timeout: propagate status to caller - return ViewItemJobInterrupted; - break; - case ViewItemJobCompleted: - // pass 3 has been completed - job->setCurrentPass( ViewItemJob::Pass4 ); - job->setStartIndex( 0 ); - job->setEndIndex( mUnassignedMessageListForPass4.count() - 1 ); - // take care of small jobs which never timeout by themselves because - // of a small number of messages. At the end of each job check - // the time used and if we're timeoutting and there is another job - // then interrupt. - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - return ViewItemJobInterrupted; - // else proceed with the next pass - break; - default: - // This is *really* a BUG - kWarning() << "ERROR: returned an invalid result"; - Q_ASSERT( false ); - break; + if ( job->currentPass() == ViewItemJob::Pass3 ) + { + // We're in Pass3 of the job. + switch ( viewItemJobStepInternalForJobPass3( job, tStart ) ) + { + case ViewItemJobInterrupted: + // current job interrupted by timeout: propagate status to caller + return ViewItemJobInterrupted; + break; + case ViewItemJobCompleted: + // pass 3 has been completed + job->setCurrentPass( ViewItemJob::Pass4 ); + job->setStartIndex( 0 ); + job->setEndIndex( mUnassignedMessageListForPass4.count() - 1 ); + // take care of small jobs which never timeout by themselves because + // of a small number of messages. At the end of each job check + // the time used and if we're timeoutting and there is another job + // then interrupt. + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + return ViewItemJobInterrupted; + // else proceed with the next pass + break; + default: + // This is *really* a BUG + kWarning() << "ERROR: returned an invalid result"; + Q_ASSERT( false ); + break; + } } - } - if ( job->currentPass() == ViewItemJob::Pass4 ) - { - // We're in Pass4 of the job. - switch ( viewItemJobStepInternalForJobPass4( job, tStart ) ) - { - case ViewItemJobInterrupted: - // current job interrupted by timeout: propagate status to caller - return ViewItemJobInterrupted; - break; - case ViewItemJobCompleted: - // pass 4 has been completed - job->setCurrentPass( ViewItemJob::Pass5 ); - job->setStartIndex( 0 ); - job->setEndIndex( mGroupHeadersThatNeedUpdate.count() - 1 ); - // take care of small jobs which never timeout by themselves because - // of a small number of messages. At the end of each job check - // the time used and if we're timeoutting and there is another job - // then interrupt. - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - return ViewItemJobInterrupted; - // else proceed with the next pass - break; - default: - // This is *really* a BUG - kWarning() << "ERROR: returned an invalid result";; - Q_ASSERT( false ); - break; + if ( job->currentPass() == ViewItemJob::Pass4 ) + { + // We're in Pass4 of the job. + switch ( viewItemJobStepInternalForJobPass4( job, tStart ) ) + { + case ViewItemJobInterrupted: + // current job interrupted by timeout: propagate status to caller + return ViewItemJobInterrupted; + break; + case ViewItemJobCompleted: + // pass 4 has been completed + job->setCurrentPass( ViewItemJob::Pass5 ); + job->setStartIndex( 0 ); + job->setEndIndex( mGroupHeadersThatNeedUpdate.count() - 1 ); + // take care of small jobs which never timeout by themselves because + // of a small number of messages. At the end of each job check + // the time used and if we're timeoutting and there is another job + // then interrupt. + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + return ViewItemJobInterrupted; + // else proceed with the next pass + break; + default: + // This is *really* a BUG + kWarning() << "ERROR: returned an invalid result";; + Q_ASSERT( false ); + break; + } } - } - // Pass4 has been already completed. Proceed to Pass5. - return viewItemJobStepInternalForJobPass5( job, tStart ); + // Pass4 has been already completed. Proceed to Pass5. + return viewItemJobStepInternalForJobPass5( job, tStart ); } #ifdef KDEPIM_FOLDEROPEN_PROFILE @@ -3561,13 +3561,13 @@ // Descriptions of the job, for nicer debug output static const char *jobDescription[numberOfPasses] = { - "Creating items from messages and simple threading", - "Removing messages", - "Updating messages", - "Additional Threading", - "Subject-Based threading", - "Grouping", - "Group resorting + cleanup" + "Creating items from messages and simple threading", + "Removing messages", + "Updating messages", + "Additional Threading", + "Subject-Based threading", + "Grouping", + "Group resorting + cleanup" }; // Timer to track time between start of first job and end of last job @@ -3579,1004 +3579,1004 @@ // Zeros the stats, to be called when the first job starts static void resetStats() { - totalMessages = 0; - layoutChangeTime = 0; - expandingTreeTime = 0; - lastPass = -1; - for ( int i = 0; i < numberOfPasses; ++i ) { - numElements[i] = 0; - totalTime[i] = 0; - chunks[i] = 0; - } + totalMessages = 0; + layoutChangeTime = 0; + expandingTreeTime = 0; + lastPass = -1; + for ( int i = 0; i < numberOfPasses; ++i ) { + numElements[i] = 0; + totalTime[i] = 0; + chunks[i] = 0; + } } } // namespace Stats void ModelPrivate::printStatistics() { - using namespace Stats; - int totalTotalTime = 0; - int completeTime = firstStartTime.elapsed(); - for ( int i = 0; i < numberOfPasses; ++i ) - totalTotalTime += totalTime[i]; - - float msgPerSecond = totalMessages / ( totalTotalTime / 1000.0f ); - float msgPerSecondComplete = totalMessages / ( completeTime / 1000.0f ); - - int messagesWithSameSubjectAvg = 0; - int messagesWithSameSubjectMax = 0; - foreach( const QList< MessageItem * > *messages, mThreadingCacheMessageSubjectMD5ToMessageItem ) { - if ( messages->size() > messagesWithSameSubjectMax ) - messagesWithSameSubjectMax = messages->size(); - messagesWithSameSubjectAvg += messages->size(); - } - messagesWithSameSubjectAvg = messagesWithSameSubjectAvg / (float)mThreadingCacheMessageSubjectMD5ToMessageItem.size(); - - int totalThreads = 0; - if ( !mGroupHeaderItemHash.isEmpty() ) { - foreach( const GroupHeaderItem *groupHeader, mGroupHeaderItemHash ) { - totalThreads += groupHeader->childItemCount(); - } - } - else - totalThreads = mRootItem->childItemCount(); - - kDebug() << "Finished filling the view with" << totalMessages << "messages"; - kDebug() << "That took" << totalTotalTime << "msecs inside the model and" - << completeTime << "in total."; - kDebug() << ( totalTotalTime / (float) completeTime ) * 100.0f - << "percent of the time was spent in the model."; - kDebug() << "Time for layoutChanged(), in msecs:" << layoutChangeTime - << "(" << (layoutChangeTime / (float)totalTotalTime) * 100.0f << "percent )"; - kDebug() << "Time to expand tree, in msecs:" << expandingTreeTime - << "(" << (expandingTreeTime / (float)totalTotalTime) * 100.0f << "percent )"; - kDebug() << "Number of messages per second in the model:" << msgPerSecond; - kDebug() << "Number of messages per second in total:" << msgPerSecondComplete; - kDebug() << "Number of threads:" << totalThreads; - kDebug() << "Number of groups:" << mGroupHeaderItemHash.size(); - kDebug() << "Messages per thread:" << totalMessages / (float)totalThreads; - kDebug() << "Threads per group:" << totalThreads / (float)mGroupHeaderItemHash.size(); - kDebug() << "Messages with the same subject:" - << "Max:" << messagesWithSameSubjectMax - << "Avg:" << messagesWithSameSubjectAvg; - kDebug(); - kDebug() << "Now follows a breakdown of the jobs."; - kDebug(); - for ( int i = 0; i < numberOfPasses; ++i ) { - if ( totalTime[i] == 0 ) - continue; - float elementsPerSecond = numElements[i] / ( totalTime[i] / 1000.0f ); - float percent = totalTime[i] / (float)totalTotalTime * 100.0f; - kDebug() << "----------------------------------------------"; - kDebug() << "Job" << i + 1 << "(" << jobDescription[i] << ")"; - kDebug() << "Share of complete time:" << percent << "percent"; - kDebug() << "Time in msecs:" << totalTime[i]; - kDebug() << "Number of elements:" << numElements[i]; // TODO: map of element string - kDebug() << "Elements per second:" << elementsPerSecond; - kDebug() << "Number of chunks:" << chunks[i]; + using namespace Stats; + int totalTotalTime = 0; + int completeTime = firstStartTime.elapsed(); + for ( int i = 0; i < numberOfPasses; ++i ) + totalTotalTime += totalTime[i]; + + float msgPerSecond = totalMessages / ( totalTotalTime / 1000.0f ); + float msgPerSecondComplete = totalMessages / ( completeTime / 1000.0f ); + + int messagesWithSameSubjectAvg = 0; + int messagesWithSameSubjectMax = 0; + foreach( const QList< MessageItem * > *messages, mThreadingCacheMessageSubjectMD5ToMessageItem ) { + if ( messages->size() > messagesWithSameSubjectMax ) + messagesWithSameSubjectMax = messages->size(); + messagesWithSameSubjectAvg += messages->size(); + } + messagesWithSameSubjectAvg = messagesWithSameSubjectAvg / (float)mThreadingCacheMessageSubjectMD5ToMessageItem.size(); + + int totalThreads = 0; + if ( !mGroupHeaderItemHash.isEmpty() ) { + foreach( const GroupHeaderItem *groupHeader, mGroupHeaderItemHash ) { + totalThreads += groupHeader->childItemCount(); + } + } + else + totalThreads = mRootItem->childItemCount(); + + kDebug() << "Finished filling the view with" << totalMessages << "messages"; + kDebug() << "That took" << totalTotalTime << "msecs inside the model and" + << completeTime << "in total."; + kDebug() << ( totalTotalTime / (float) completeTime ) * 100.0f + << "percent of the time was spent in the model."; + kDebug() << "Time for layoutChanged(), in msecs:" << layoutChangeTime + << "(" << (layoutChangeTime / (float)totalTotalTime) * 100.0f << "percent )"; + kDebug() << "Time to expand tree, in msecs:" << expandingTreeTime + << "(" << (expandingTreeTime / (float)totalTotalTime) * 100.0f << "percent )"; + kDebug() << "Number of messages per second in the model:" << msgPerSecond; + kDebug() << "Number of messages per second in total:" << msgPerSecondComplete; + kDebug() << "Number of threads:" << totalThreads; + kDebug() << "Number of groups:" << mGroupHeaderItemHash.size(); + kDebug() << "Messages per thread:" << totalMessages / (float)totalThreads; + kDebug() << "Threads per group:" << totalThreads / (float)mGroupHeaderItemHash.size(); + kDebug() << "Messages with the same subject:" + << "Max:" << messagesWithSameSubjectMax + << "Avg:" << messagesWithSameSubjectAvg; kDebug(); - } + kDebug() << "Now follows a breakdown of the jobs."; + kDebug(); + for ( int i = 0; i < numberOfPasses; ++i ) { + if ( totalTime[i] == 0 ) + continue; + float elementsPerSecond = numElements[i] / ( totalTime[i] / 1000.0f ); + float percent = totalTime[i] / (float)totalTotalTime * 100.0f; + kDebug() << "----------------------------------------------"; + kDebug() << "Job" << i + 1 << "(" << jobDescription[i] << ")"; + kDebug() << "Share of complete time:" << percent << "percent"; + kDebug() << "Time in msecs:" << totalTime[i]; + kDebug() << "Number of elements:" << numElements[i]; // TODO: map of element string + kDebug() << "Elements per second:" << elementsPerSecond; + kDebug() << "Number of chunks:" << chunks[i]; + kDebug(); + } - kDebug() << "=========================================================="; - resetStats(); + kDebug() << "=========================================================="; + resetStats(); } #endif ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternal() { - // This function does a timed chunk of work in our View Fill operation. - // It attempts to do processing until it either runs out of jobs - // to be done or a timeout forces it to interrupt and jump back to the caller. - - QTime tStart = QTime::currentTime(); - int elapsed; - - while( !mViewItemJobs.isEmpty() ) - { - // Have a job to do. - ViewItemJob * job = mViewItemJobs.first(); + // This function does a timed chunk of work in our View Fill operation. + // It attempts to do processing until it either runs out of jobs + // to be done or a timeout forces it to interrupt and jump back to the caller. + + QTime tStart = QTime::currentTime(); + int elapsed; + + while( !mViewItemJobs.isEmpty() ) + { + // Have a job to do. + ViewItemJob * job = mViewItemJobs.first(); #ifdef KDEPIM_FOLDEROPEN_PROFILE - // Here we check if an old job has just completed or if we are at the start of the - // first job. We then initialize job data stuff and timers based on this. + // Here we check if an old job has just completed or if we are at the start of the + // first job. We then initialize job data stuff and timers based on this. - const int currentPass = job->currentPass(); - const bool firstChunk = currentPass != Stats::lastPass; - if ( currentPass != Stats::lastPass && Stats::lastPass != -1 ) { - Stats::totalTime[Stats::lastPass] = Stats::currentJobStartTime.elapsed(); - } - const bool firstJob = job->currentPass() == ViewItemJob::Pass1Fill && firstChunk; - const int elements = job->endIndex() - job->startIndex(); - if ( firstJob ) { - Stats::resetStats(); - Stats::totalMessages = elements; - Stats::firstStartTime.restart(); - } - if ( firstChunk ) { - Stats::numElements[currentPass] = elements; - Stats::currentJobStartTime.restart(); - } - Stats::chunks[currentPass]++; - Stats::lastPass = currentPass; + const int currentPass = job->currentPass(); + const bool firstChunk = currentPass != Stats::lastPass; + if ( currentPass != Stats::lastPass && Stats::lastPass != -1 ) { + Stats::totalTime[Stats::lastPass] = Stats::currentJobStartTime.elapsed(); + } + const bool firstJob = job->currentPass() == ViewItemJob::Pass1Fill && firstChunk; + const int elements = job->endIndex() - job->startIndex(); + if ( firstJob ) { + Stats::resetStats(); + Stats::totalMessages = elements; + Stats::firstStartTime.restart(); + } + if ( firstChunk ) { + Stats::numElements[currentPass] = elements; + Stats::currentJobStartTime.restart(); + } + Stats::chunks[currentPass]++; + Stats::lastPass = currentPass; #endif - mViewItemJobStepIdleInterval = job->idleInterval(); - mViewItemJobStepChunkTimeout = job->chunkTimeout(); - mViewItemJobStepMessageCheckCount = job->messageCheckCount(); - - if ( job->disconnectUI() ) - { - mModelForItemFunctions = 0; // disconnect the UI for this job - Q_ASSERT( mLoading ); // this must be true in the first job - // FIXME: Should assert yet more that this is the very first job for this StorageModel - // Asserting only mLoading is not enough as we could be using a two-jobs loading strategy - // or this could be a job enqueued before the first job has completed. - } else { - // With a connected UI we need to avoid the view to update the scrollbars at EVERY insertion or expansion. - // QTreeViewPrivate::updateScrollBars() is very expensive as it loops through ALL the items in the view every time. - // We can't disable the function directly as it's hidden in the private data object of QTreeView - // but we can disable the parent QTreeView::updateGeometries() instead. - // We will trigger it "manually" at the end of the step. - mView->ignoreUpdateGeometries( true ); - - // Ok.. I know that this seems unbelieveable but disabling updates actually - // causes a (significant) performance loss in most cases. This is probably because QTreeView - // uses delayed layouts when updates are disabled which should be delayed but in - // fact are "forced" by next item insertions. The delayed layout algorithm, then - // is probably slower than the non-delayed one. - // Disabling the paintEvent() doesn't seem to work either. - //mView->setUpdatesEnabled( false ); - } - - switch( viewItemJobStepInternalForJob( job, tStart ) ) - { - case ViewItemJobInterrupted: - { - // current job interrupted by timeout: will propagate status to caller - // but before this, give some feedback to the user - - // FIXME: This is now inaccurate, think of something else - switch( job->currentPass() ) - { - case ViewItemJob::Pass1Fill: - case ViewItemJob::Pass1Cleanup: - case ViewItemJob::Pass1Update: - emit q->statusMessage( i18np( "Processed 1 Message of %2", - "Processed %1 Messages of %2", - job->currentIndex() - job->startIndex(), - job->endIndex() - job->startIndex() + 1 ) ); - break; - case ViewItemJob::Pass2: - emit q->statusMessage( i18np( "Threaded 1 Message of %2", - "Threaded %1 Messages of %2", - job->currentIndex() - job->startIndex(), - job->endIndex() - job->startIndex() + 1 ) ); - break; - case ViewItemJob::Pass3: - emit q->statusMessage( i18np( "Threaded 1 Message of %2", - "Threaded %1 Messages of %2", - job->currentIndex() - job->startIndex(), - job->endIndex() - job->startIndex() + 1 ) ); - break; - case ViewItemJob::Pass4: - emit q->statusMessage( i18np( "Grouped 1 Thread of %2", - "Grouped %1 Threads of %2", - job->currentIndex() - job->startIndex(), - job->endIndex() - job->startIndex() + 1 ) ); - break; - case ViewItemJob::Pass5: - emit q->statusMessage( i18np( "Updated 1 Group of %2", - "Updated %1 Groups of %2", - job->currentIndex() - job->startIndex(), - job->endIndex() - job->startIndex() + 1 ) ); - break; - default: break; - } - - if( !job->disconnectUI() ) - { - mView->ignoreUpdateGeometries( false ); - // explicit call to updateGeometries() here - mView->updateGeometries(); - } - - return ViewItemJobInterrupted; - } - break; - case ViewItemJobCompleted: + mViewItemJobStepIdleInterval = job->idleInterval(); + mViewItemJobStepChunkTimeout = job->chunkTimeout(); + mViewItemJobStepMessageCheckCount = job->messageCheckCount(); - // If this job worked with a disconnected UI, emit layoutChanged() - // to reconnect it. We go back to normal operation now. if ( job->disconnectUI() ) { - mModelForItemFunctions = q; - // This call would destroy the expanded state of items. - // This is why when mModelForItemFunctions was 0 we didn't actually expand them - // but we just set a "ExpandNeeded" mark... + mModelForItemFunctions = 0; // disconnect the UI for this job + Q_ASSERT( mLoading ); // this must be true in the first job + // FIXME: Should assert yet more that this is the very first job for this StorageModel + // Asserting only mLoading is not enough as we could be using a two-jobs loading strategy + // or this could be a job enqueued before the first job has completed. + } else { + // With a connected UI we need to avoid the view to update the scrollbars at EVERY insertion or expansion. + // QTreeViewPrivate::updateScrollBars() is very expensive as it loops through ALL the items in the view every time. + // We can't disable the function directly as it's hidden in the private data object of QTreeView + // but we can disable the parent QTreeView::updateGeometries() instead. + // We will trigger it "manually" at the end of the step. + mView->ignoreUpdateGeometries( true ); + + // Ok.. I know that this seems unbelieveable but disabling updates actually + // causes a (significant) performance loss in most cases. This is probably because QTreeView + // uses delayed layouts when updates are disabled which should be delayed but in + // fact are "forced" by next item insertions. The delayed layout algorithm, then + // is probably slower than the non-delayed one. + // Disabling the paintEvent() doesn't seem to work either. + //mView->setUpdatesEnabled( false ); + } + + switch( viewItemJobStepInternalForJob( job, tStart ) ) + { + case ViewItemJobInterrupted: + { + // current job interrupted by timeout: will propagate status to caller + // but before this, give some feedback to the user + + // FIXME: This is now inaccurate, think of something else + switch( job->currentPass() ) + { + case ViewItemJob::Pass1Fill: + case ViewItemJob::Pass1Cleanup: + case ViewItemJob::Pass1Update: + emit q->statusMessage( i18np( "Processed 1 Message of %2", + "Processed %1 Messages of %2", + job->currentIndex() - job->startIndex(), + job->endIndex() - job->startIndex() + 1 ) ); + break; + case ViewItemJob::Pass2: + emit q->statusMessage( i18np( "Threaded 1 Message of %2", + "Threaded %1 Messages of %2", + job->currentIndex() - job->startIndex(), + job->endIndex() - job->startIndex() + 1 ) ); + break; + case ViewItemJob::Pass3: + emit q->statusMessage( i18np( "Threaded 1 Message of %2", + "Threaded %1 Messages of %2", + job->currentIndex() - job->startIndex(), + job->endIndex() - job->startIndex() + 1 ) ); + break; + case ViewItemJob::Pass4: + emit q->statusMessage( i18np( "Grouped 1 Thread of %2", + "Grouped %1 Threads of %2", + job->currentIndex() - job->startIndex(), + job->endIndex() - job->startIndex() + 1 ) ); + break; + case ViewItemJob::Pass5: + emit q->statusMessage( i18np( "Updated 1 Group of %2", + "Updated %1 Groups of %2", + job->currentIndex() - job->startIndex(), + job->endIndex() - job->startIndex() + 1 ) ); + break; + default: break; + } + + if( !job->disconnectUI() ) + { + mView->ignoreUpdateGeometries( false ); + // explicit call to updateGeometries() here + mView->updateGeometries(); + } + + return ViewItemJobInterrupted; + } + break; + case ViewItemJobCompleted: + + // If this job worked with a disconnected UI, emit layoutChanged() + // to reconnect it. We go back to normal operation now. + if ( job->disconnectUI() ) + { + mModelForItemFunctions = q; + // This call would destroy the expanded state of items. + // This is why when mModelForItemFunctions was 0 we didn't actually expand them + // but we just set a "ExpandNeeded" mark... #ifdef KDEPIM_FOLDEROPEN_PROFILE - QTime layoutChangedTimer; - layoutChangedTimer.start(); + QTime layoutChangedTimer; + layoutChangedTimer.start(); #endif - mView->modelAboutToEmitLayoutChanged(); - emit q->layoutChanged(); - mView->modelEmittedLayoutChanged(); + mView->modelAboutToEmitLayoutChanged(); + emit q->layoutChanged(); + mView->modelEmittedLayoutChanged(); #ifdef KDEPIM_FOLDEROPEN_PROFILE - Stats::layoutChangeTime = layoutChangedTimer.elapsed(); - QTime expandingTime; - expandingTime.start(); + Stats::layoutChangeTime = layoutChangedTimer.elapsed(); + QTime expandingTime; + expandingTime.start(); #endif - // expand all the items that need it in a single sweep + // expand all the items that need it in a single sweep - // FIXME: This takes quite a lot of time, it could be made an interruptible job + // FIXME: This takes quite a lot of time, it could be made an interruptible job - QList< Item * > * rootChildItems = mRootItem->childItems(); - if ( rootChildItems ) - { - QList< Item * >::ConstIterator end( rootChildItems->constEnd() ); - for ( QList< Item * >::ConstIterator it = rootChildItems->constBegin(); it != end ;++it ) - { - if ( ( *it )->initialExpandStatus() == Item::ExpandNeeded ) - syncExpandedStateOfSubtree( *it ); - } - } + QList< Item * > * rootChildItems = mRootItem->childItems(); + if ( rootChildItems ) + { + QList< Item * >::ConstIterator end( rootChildItems->constEnd() ); + for ( QList< Item * >::ConstIterator it = rootChildItems->constBegin(); it != end ;++it ) + { + if ( ( *it )->initialExpandStatus() == Item::ExpandNeeded ) + syncExpandedStateOfSubtree( *it ); + } + } #ifdef KDEPIM_FOLDEROPEN_PROFILE - Stats::expandingTreeTime = expandingTime.elapsed(); + Stats::expandingTreeTime = expandingTime.elapsed(); #endif - } else { - mView->ignoreUpdateGeometries( false ); - // explicit call to updateGeometries() here - mView->updateGeometries(); - } + } else { + mView->ignoreUpdateGeometries( false ); + // explicit call to updateGeometries() here + mView->updateGeometries(); + } - // this job has been completed - delete mViewItemJobs.takeFirst(); + // this job has been completed + delete mViewItemJobs.takeFirst(); #ifdef KDEPIM_FOLDEROPEN_PROFILE - // Last job finished! - Stats::totalTime[currentPass] = Stats::currentJobStartTime.elapsed(); - printStatistics(); + // Last job finished! + Stats::totalTime[currentPass] = Stats::currentJobStartTime.elapsed(); + printStatistics(); #endif - // take care of small jobs which never timeout by themselves because - // of a small number of messages. At the end of each job check - // the time used and if we're timeoutting and there is another job - // then interrupt. - elapsed = tStart.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) - { - if ( !mViewItemJobs.isEmpty() ) - return ViewItemJobInterrupted; - // else it's completed in fact - } // else proceed with the next job + // take care of small jobs which never timeout by themselves because + // of a small number of messages. At the end of each job check + // the time used and if we're timeoutting and there is another job + // then interrupt. + elapsed = tStart.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mViewItemJobStepChunkTimeout ) || ( elapsed < 0 ) ) + { + if ( !mViewItemJobs.isEmpty() ) + return ViewItemJobInterrupted; + // else it's completed in fact + } // else proceed with the next job - break; - default: - // This is *really* a BUG - kWarning() << "ERROR: returned an invalid result"; - Q_ASSERT( false ); - break; + break; + default: + // This is *really* a BUG + kWarning() << "ERROR: returned an invalid result"; + Q_ASSERT( false ); + break; + } } - } - // no more jobs + // no more jobs - emit q->statusMessage( i18nc( "@info:status Finished view fill", "Ready" ) ); + emit q->statusMessage( i18nc( "@info:status Finished view fill", "Ready" ) ); - return ViewItemJobCompleted; + return ViewItemJobCompleted; } void ModelPrivate::viewItemJobStep() { - // A single step in the View Fill operation. - // This function wraps viewItemJobStepInternal() which does the step job - // and either completes it or stops because of a timeout. - // If the job is stopped then we start a zero-msecs timer to call us - // back and resume the job. Otherwise we're just done. + // A single step in the View Fill operation. + // This function wraps viewItemJobStepInternal() which does the step job + // and either completes it or stops because of a timeout. + // If the job is stopped then we start a zero-msecs timer to call us + // back and resume the job. Otherwise we're just done. - mViewItemJobStepStartTime = ::time( 0 ); + mViewItemJobStepStartTime = ::time( 0 ); - if( mFillStepTimer.isActive() ) - mFillStepTimer.stop(); + if( mFillStepTimer.isActive() ) + mFillStepTimer.stop(); - if ( !mStorageModel ) - return; // nothing more to do + if ( !mStorageModel ) + return; // nothing more to do - // Save the current item in the view as our process may - // cause items to be reparented (and QTreeView will forget the current item in the meantime). - // This machinery is also needed when we're about to remove items from the view in - // a cleanup job: we'll be trying to set as current the item after the one removed. + // Save the current item in the view as our process may + // cause items to be reparented (and QTreeView will forget the current item in the meantime). + // This machinery is also needed when we're about to remove items from the view in + // a cleanup job: we'll be trying to set as current the item after the one removed. - QModelIndex currentIndexBeforeStep = mView->currentIndex(); - Item * currentItemBeforeStep = currentIndexBeforeStep.isValid() ? - static_cast< Item * >( currentIndexBeforeStep.internalPointer() ) : 0; + QModelIndex currentIndexBeforeStep = mView->currentIndex(); + Item * currentItemBeforeStep = currentIndexBeforeStep.isValid() ? + static_cast< Item * >( currentIndexBeforeStep.internalPointer() ) : 0; - // mCurrentItemToRestoreAfterViewItemJobStep will be zeroed out if it's killed - mCurrentItemToRestoreAfterViewItemJobStep = currentItemBeforeStep; + // mCurrentItemToRestoreAfterViewItemJobStep will be zeroed out if it's killed + mCurrentItemToRestoreAfterViewItemJobStep = currentItemBeforeStep; - // Save the current item position in the viewport as QTreeView fails to keep - // the current item in the sample place when items are added or removed... - QRect rectBeforeViewItemJobStep; + // Save the current item position in the viewport as QTreeView fails to keep + // the current item in the sample place when items are added or removed... + QRect rectBeforeViewItemJobStep; - const bool lockView = mView->isScrollingLocked(); + const bool lockView = mView->isScrollingLocked(); - // This is generally SLOW AS HELL... (so we avoid it if we lock the view and thus don't need it) - if ( mCurrentItemToRestoreAfterViewItemJobStep && ( !lockView ) ) - rectBeforeViewItemJobStep = mView->visualRect( currentIndexBeforeStep ); + // This is generally SLOW AS HELL... (so we avoid it if we lock the view and thus don't need it) + if ( mCurrentItemToRestoreAfterViewItemJobStep && ( !lockView ) ) + rectBeforeViewItemJobStep = mView->visualRect( currentIndexBeforeStep ); - // FIXME: If the current item is NOT in the view, preserve the position - // of the top visible item. This will make the view move yet less. + // FIXME: If the current item is NOT in the view, preserve the position + // of the top visible item. This will make the view move yet less. - // Insulate the View from (very likely spurious) "currentChanged()" signals. - mView->ignoreCurrentChanges( true ); + // Insulate the View from (very likely spurious) "currentChanged()" signals. + mView->ignoreCurrentChanges( true ); - // And go to real work. - switch( viewItemJobStepInternal() ) - { + // And go to real work. + switch( viewItemJobStepInternal() ) + { case ViewItemJobInterrupted: - // Operation timed out, need to resume in a while - if ( !mInLengthyJobBatch ) - { - mInLengthyJobBatch = true; - mView->modelJobBatchStarted(); - } - mFillStepTimer.start( mViewItemJobStepIdleInterval ); // this is a single shot timer connected to viewItemJobStep() - // and go dealing with current/selection out of the switch. - break; + // Operation timed out, need to resume in a while + if ( !mInLengthyJobBatch ) + { + mInLengthyJobBatch = true; + mView->modelJobBatchStarted(); + } + mFillStepTimer.start( mViewItemJobStepIdleInterval ); // this is a single shot timer connected to viewItemJobStep() + // and go dealing with current/selection out of the switch. + break; case ViewItemJobCompleted: - // done :) - - Q_ASSERT( mModelForItemFunctions ); // UI must be no (longer) disconnected in this state + // done :) - // Ask the view to remove the eventual busy indications - if ( mInLengthyJobBatch ) - { - mInLengthyJobBatch = false; - mView->modelJobBatchTerminated(); - } + Q_ASSERT( mModelForItemFunctions ); // UI must be no (longer) disconnected in this state - if ( mLoading ) - { - mLoading = false; - mView->modelFinishedLoading(); - } - - // Apply pre-selection, if any - if ( mPreSelectionMode != PreSelectNone ) - { - mView->ignoreCurrentChanges( false ); + // Ask the view to remove the eventual busy indications + if ( mInLengthyJobBatch ) + { + mInLengthyJobBatch = false; + mView->modelJobBatchTerminated(); + } - bool bSelectionDone = false; + if ( mLoading ) + { + mLoading = false; + mView->modelFinishedLoading(); + } - switch( mPreSelectionMode ) + // Apply pre-selection, if any + if ( mPreSelectionMode != PreSelectNone ) { - case PreSelectLastSelected: - // fall down - break; - case PreSelectFirstUnreadCentered: - bSelectionDone = mView->selectFirstMessageItem( MessageTypeUnreadOnly, true ); // center - break; - case PreSelectOldestCentered: - mView->setCurrentMessageItem( mOldestItem, true /* center */ ); - bSelectionDone = true; - break; - case PreSelectNewestCentered: - mView->setCurrentMessageItem( mNewestItem, true /* center */ ); - bSelectionDone = true; - break; - case PreSelectNone: - // deal with selection below - break; - default: - kWarning() << "ERROR: Unrecognized pre-selection mode " << (int)mPreSelectionMode; - break; - } - - if ( ( !bSelectionDone ) && ( mPreSelectionMode != PreSelectNone ) ) - { - // fallback to last selected, if possible - if ( mLastSelectedMessageInFolder ) // we found it in the loading process: select and jump out - { - mView->setCurrentMessageItem( mLastSelectedMessageInFolder ); - bSelectionDone = true; - } - } - - if ( bSelectionDone ) { - mLastSelectedMessageInFolder = 0; - mPreSelectionMode = PreSelectNone; - return; // already taken care of current / selection + mView->ignoreCurrentChanges( false ); + + bool bSelectionDone = false; + + switch( mPreSelectionMode ) + { + case PreSelectLastSelected: + // fall down + break; + case PreSelectFirstUnreadCentered: + bSelectionDone = mView->selectFirstMessageItem( MessageTypeUnreadOnly, true ); // center + break; + case PreSelectOldestCentered: + mView->setCurrentMessageItem( mOldestItem, true /* center */ ); + bSelectionDone = true; + break; + case PreSelectNewestCentered: + mView->setCurrentMessageItem( mNewestItem, true /* center */ ); + bSelectionDone = true; + break; + case PreSelectNone: + // deal with selection below + break; + default: + kWarning() << "ERROR: Unrecognized pre-selection mode " << (int)mPreSelectionMode; + break; + } + + if ( ( !bSelectionDone ) && ( mPreSelectionMode != PreSelectNone ) ) + { + // fallback to last selected, if possible + if ( mLastSelectedMessageInFolder ) // we found it in the loading process: select and jump out + { + mView->setCurrentMessageItem( mLastSelectedMessageInFolder ); + bSelectionDone = true; + } + } + + if ( bSelectionDone ) { + mLastSelectedMessageInFolder = 0; + mPreSelectionMode = PreSelectNone; + return; // already taken care of current / selection + } } - } - // deal with current/selection out of the switch + // deal with current/selection out of the switch - break; + break; default: - // This is *really* a BUG - kWarning() << "ERROR: returned an invalid result"; - Q_ASSERT( false ); - break; - } - - // Everything else here deals with the selection - - // If UI is disconnected then we don't have anything else to do here - if ( !mModelForItemFunctions ) - { - mView->ignoreCurrentChanges( false ); - return; - } - - // Restore current/selection and/or scrollbar position + // This is *really* a BUG + kWarning() << "ERROR: returned an invalid result"; + Q_ASSERT( false ); + break; + } - if ( mCurrentItemToRestoreAfterViewItemJobStep ) - { - bool stillIgnoringCurrentChanges = true; - - // If the assert below fails then the previously current item got detached - // and didn't get reattached in the step: this should never happen. - Q_ASSERT( mCurrentItemToRestoreAfterViewItemJobStep->isViewable() ); - - // Check if the current item changed - QModelIndex currentIndexAfterStep = mView->currentIndex(); - Item * currentAfterStep = currentIndexAfterStep.isValid() ? - static_cast< Item * >( currentIndexAfterStep.internalPointer() ) : 0; - - if ( mCurrentItemToRestoreAfterViewItemJobStep != currentAfterStep ) - { - // QTreeView lost the current item... - if ( mCurrentItemToRestoreAfterViewItemJobStep != currentItemBeforeStep ) - { - // Some view job code expects us to actually *change* the current item. - // This is done by the cleanup step which removes items and tries - // to set as current the item *after* the removed one, if possible. - // We need the view to handle the change though. - stillIgnoringCurrentChanges = false; - mView->ignoreCurrentChanges( false ); - } else { - // we just have to restore the old current item. The code - // outside shouldn't have noticed that we lost it (e.g. the message viewer - // still should have the old message opened). So we don't need to - // actually notify the view of the restored setting. - } - // Restore it - kDebug() << "Gonna restore current here" << mCurrentItemToRestoreAfterViewItemJobStep->subject(); - mView->setCurrentIndex( q->index( mCurrentItemToRestoreAfterViewItemJobStep, 0 ) ); - } else { - // The item we're expected to set as current is already current - if ( mCurrentItemToRestoreAfterViewItemJobStep != currentItemBeforeStep ) - { - // But we have changed it in the job step. - // This means that: we have deleted the current item and chosen a - // new candidate as current but Qt also has chosen it as candidate - // and already made it current. The problem is that (as of Qt 4.4) - // it probably didn't select it. - if ( !mView->selectionModel()->hasSelection() ) - { - stillIgnoringCurrentChanges = false; - mView->ignoreCurrentChanges( false ); - - kDebug() << "Gonna restore selection here" << mCurrentItemToRestoreAfterViewItemJobStep->subject(); - - QItemSelection selection; - selection.append( QItemSelectionRange( q->index( mCurrentItemToRestoreAfterViewItemJobStep, 0 ) ) ); - mView->selectionModel()->select( selection, QItemSelectionModel::Select | QItemSelectionModel::Rows ); - } - } - } - - // FIXME: If it was selected before the change, then re-select it (it may happen that it's not) - if ( !lockView ) - { - // we prefer to keep the currently selected item steady in the view - QRect rectAfterViewItemJobStep = mView->visualRect( q->index( mCurrentItemToRestoreAfterViewItemJobStep, 0 ) ); - if ( rectBeforeViewItemJobStep.y() != rectAfterViewItemJobStep.y() ) - { - // QTreeView lost its position... - mView->verticalScrollBar()->setValue( mView->verticalScrollBar()->value() + rectAfterViewItemJobStep.y() - rectBeforeViewItemJobStep.y() ); - } - } - - // and kill the insulation, if not yet done - if ( stillIgnoringCurrentChanges ) - mView->ignoreCurrentChanges( false ); - - return; - } - - // Either there was no current item before, or it was lost in a cleanup step and another candidate for - // current item couldn't be found (possibly empty view) - mView->ignoreCurrentChanges( false ); - - if ( currentItemBeforeStep ) - { - // lost in a cleanup.. - // tell the view that we have a new current, this time with no insulation - mView->slotSelectionChanged( QItemSelection(), QItemSelection() ); - } -} + // Everything else here deals with the selection -void ModelPrivate::slotStorageModelRowsInserted( const QModelIndex &parent, int from, int to ) -{ - if ( parent.isValid() ) - return; // ugh... should never happen + // If UI is disconnected then we don't have anything else to do here + if ( !mModelForItemFunctions ) + { + mView->ignoreCurrentChanges( false ); + return; + } - Q_ASSERT( from <= to ); + // Restore current/selection and/or scrollbar position - int count = ( to - from ) + 1; + if ( mCurrentItemToRestoreAfterViewItemJobStep ) + { + bool stillIgnoringCurrentChanges = true; - mInvariantRowMapper->modelRowsInserted( from, count ); + // If the assert below fails then the previously current item got detached + // and didn't get reattached in the step: this should never happen. + Q_ASSERT( mCurrentItemToRestoreAfterViewItemJobStep->isViewable() ); - // look if no current job is in the middle + // Check if the current item changed + QModelIndex currentIndexAfterStep = mView->currentIndex(); + Item * currentAfterStep = currentIndexAfterStep.isValid() ? + static_cast< Item * >( currentIndexAfterStep.internalPointer() ) : 0; - int jobCount = mViewItemJobs.count(); + if ( mCurrentItemToRestoreAfterViewItemJobStep != currentAfterStep ) + { + // QTreeView lost the current item... + if ( mCurrentItemToRestoreAfterViewItemJobStep != currentItemBeforeStep ) + { + // Some view job code expects us to actually *change* the current item. + // This is done by the cleanup step which removes items and tries + // to set as current the item *after* the removed one, if possible. + // We need the view to handle the change though. + stillIgnoringCurrentChanges = false; + mView->ignoreCurrentChanges( false ); + } else { + // we just have to restore the old current item. The code + // outside shouldn't have noticed that we lost it (e.g. the message viewer + // still should have the old message opened). So we don't need to + // actually notify the view of the restored setting. + } + // Restore it + kDebug() << "Gonna restore current here" << mCurrentItemToRestoreAfterViewItemJobStep->subject(); + mView->setCurrentIndex( q->index( mCurrentItemToRestoreAfterViewItemJobStep, 0 ) ); + } else { + // The item we're expected to set as current is already current + if ( mCurrentItemToRestoreAfterViewItemJobStep != currentItemBeforeStep ) + { + // But we have changed it in the job step. + // This means that: we have deleted the current item and chosen a + // new candidate as current but Qt also has chosen it as candidate + // and already made it current. The problem is that (as of Qt 4.4) + // it probably didn't select it. + if ( !mView->selectionModel()->hasSelection() ) + { + stillIgnoringCurrentChanges = false; + mView->ignoreCurrentChanges( false ); + + kDebug() << "Gonna restore selection here" << mCurrentItemToRestoreAfterViewItemJobStep->subject(); + + QItemSelection selection; + selection.append( QItemSelectionRange( q->index( mCurrentItemToRestoreAfterViewItemJobStep, 0 ) ) ); + mView->selectionModel()->select( selection, QItemSelectionModel::Select | QItemSelectionModel::Rows ); + } + } + } - for ( int idx = 0; idx < jobCount; idx++ ) - { - ViewItemJob * job = mViewItemJobs.at( idx ); + // FIXME: If it was selected before the change, then re-select it (it may happen that it's not) + if ( !lockView ) + { + // we prefer to keep the currently selected item steady in the view + QRect rectAfterViewItemJobStep = mView->visualRect( q->index( mCurrentItemToRestoreAfterViewItemJobStep, 0 ) ); + if ( rectBeforeViewItemJobStep.y() != rectAfterViewItemJobStep.y() ) + { + // QTreeView lost its position... + mView->verticalScrollBar()->setValue( mView->verticalScrollBar()->value() + rectAfterViewItemJobStep.y() - rectBeforeViewItemJobStep.y() ); + } + } - if ( job->currentPass() != ViewItemJob::Pass1Fill ) - { - // The job is a cleanup or in a later pass: the storage has been already accessed - // and the messages created... no need to care anymore: the invariant row mapper will do the job. - continue; - } + // and kill the insulation, if not yet done + if ( stillIgnoringCurrentChanges ) + mView->ignoreCurrentChanges( false ); - if ( job->currentIndex() > job->endIndex() ) - { - // The job finished the Pass1Fill but still waits for the pass indicator to be - // changed. This is unlikely but still may happen if the job has been interrupted - // and then a call to slotStorageModelRowsRemoved() caused it to be forcibly completed. - continue; + return; } - // - // The following cases are possible: - // - // from to - // | | -> shift up job - // from to - // | | -> shift up job - // from to - // | | -> shift up job - // from to - // | | -> split job - // from to - // | | -> split job - // from to - // | | -> job unaffected - // - // - // FOLDER - // |-------------------------|---------|--------------| - // 0 currentIndex endIndex count - // +-- job --+ - // + // Either there was no current item before, or it was lost in a cleanup step and another candidate for + // current item couldn't be found (possibly empty view) + mView->ignoreCurrentChanges( false ); - if ( from > job->endIndex() ) + if ( currentItemBeforeStep ) { - // The change is completely above the job, the job is not affected - continue; + // lost in a cleanup.. + // tell the view that we have a new current, this time with no insulation + mView->slotSelectionChanged( QItemSelection(), QItemSelection() ); } +} - if( from > job->currentIndex() ) // and from <= job->endIndex() - { - // The change starts in the middle of the job in a way that it must be split in two. - // The first part is unaffected by the shift and ranges from job->currentIndex() to from - 1. - // The second part ranges from "from" to job->endIndex() that are now shifted up by count steps. +void ModelPrivate::slotStorageModelRowsInserted( const QModelIndex &parent, int from, int to ) +{ + if ( parent.isValid() ) + return; // ugh... should never happen - // First add a new job for the second part. - ViewItemJob * newJob = new ViewItemJob( from + count, job->endIndex() + count, job->chunkTimeout(), job->idleInterval(), job->messageCheckCount() ); + Q_ASSERT( from <= to ); - Q_ASSERT( newJob->currentIndex() <= newJob->endIndex() ); + int count = ( to - from ) + 1; - idx++; // we can skip this job in the loop, it's already ok - jobCount++; // and our range increases by one. - mViewItemJobs.insert( idx, newJob ); + mInvariantRowMapper->modelRowsInserted( from, count ); - // Then limit the original job to the first part - job->setEndIndex( from - 1 ); + // look if no current job is in the middle - Q_ASSERT( job->currentIndex() <= job->endIndex() ); + int jobCount = mViewItemJobs.count(); - continue; - } + for ( int idx = 0; idx < jobCount; idx++ ) + { + ViewItemJob * job = mViewItemJobs.at( idx ); - // The change starts below (or exactly on the beginning of) the job. - // The job must be shifted up. - job->setCurrentIndex( job->currentIndex() + count ); - job->setEndIndex( job->endIndex() + count ); + if ( job->currentPass() != ViewItemJob::Pass1Fill ) + { + // The job is a cleanup or in a later pass: the storage has been already accessed + // and the messages created... no need to care anymore: the invariant row mapper will do the job. + continue; + } - Q_ASSERT( job->currentIndex() <= job->endIndex() ); - } + if ( job->currentIndex() > job->endIndex() ) + { + // The job finished the Pass1Fill but still waits for the pass indicator to be + // changed. This is unlikely but still may happen if the job has been interrupted + // and then a call to slotStorageModelRowsRemoved() caused it to be forcibly completed. + continue; + } - bool newJobNeeded = true; + // + // The following cases are possible: + // + // from to + // | | -> shift up job + // from to + // | | -> shift up job + // from to + // | | -> shift up job + // from to + // | | -> split job + // from to + // | | -> split job + // from to + // | | -> job unaffected + // + // + // FOLDER + // |-------------------------|---------|--------------| + // 0 currentIndex endIndex count + // +-- job --+ + // - // Try to attach to an existing fill job, if any. - // To enforce consistency we can attach only if the Fill job - // is the last one in the list (might be eventually *also* the first, - // and even being already processed but we must make sure that there - // aren't jobs _after_ it). - if ( jobCount > 0 ) - { - ViewItemJob * job = mViewItemJobs.at( jobCount - 1 ); - if ( job->currentPass() == ViewItemJob::Pass1Fill ) - { - if ( - // The job ends just before the added rows - ( from == ( job->endIndex() + 1 ) ) && - // The job didn't reach the end of Pass1Fill yet - ( job->currentIndex() <= job->endIndex() ) - ) - { - // We can still attach this :) - job->setEndIndex( to ); - Q_ASSERT( job->currentIndex() <= job->endIndex() ); - newJobNeeded = false; - } - } - } + if ( from > job->endIndex() ) + { + // The change is completely above the job, the job is not affected + continue; + } - if ( newJobNeeded ) - { - // FIXME: Should take timing options from aggregation here ? - ViewItemJob * job = new ViewItemJob( from, to, 100, 50, 10 ); - mViewItemJobs.append( job ); - } + if( from > job->currentIndex() ) // and from <= job->endIndex() + { + // The change starts in the middle of the job in a way that it must be split in two. + // The first part is unaffected by the shift and ranges from job->currentIndex() to from - 1. + // The second part ranges from "from" to job->endIndex() that are now shifted up by count steps. - if ( !mFillStepTimer.isActive() ) - mFillStepTimer.start( mViewItemJobStepIdleInterval ); -} + // First add a new job for the second part. + ViewItemJob * newJob = new ViewItemJob( from + count, job->endIndex() + count, job->chunkTimeout(), job->idleInterval(), job->messageCheckCount() ); -void ModelPrivate::slotStorageModelRowsRemoved( const QModelIndex &parent, int from, int to ) -{ - // This is called when the underlying StorageModel emits the rowsRemoved signal. + Q_ASSERT( newJob->currentIndex() <= newJob->endIndex() ); - if ( parent.isValid() ) - return; // ugh... should never happen + idx++; // we can skip this job in the loop, it's already ok + jobCount++; // and our range increases by one. + mViewItemJobs.insert( idx, newJob ); - // look if no current job is in the middle + // Then limit the original job to the first part + job->setEndIndex( from - 1 ); - Q_ASSERT( from <= to ); + Q_ASSERT( job->currentIndex() <= job->endIndex() ); - const int count = ( to - from ) + 1; + continue; + } - int jobCount = mViewItemJobs.count(); + // The change starts below (or exactly on the beginning of) the job. + // The job must be shifted up. + job->setCurrentIndex( job->currentIndex() + count ); + job->setEndIndex( job->endIndex() + count ); - if (mRootItem && from == 0 && count == mRootItem->childItemCount() && jobCount == 0) { - clear(); - return; - } + Q_ASSERT( job->currentIndex() <= job->endIndex() ); + } - for ( int idx = 0; idx < jobCount; idx++ ) - { - ViewItemJob * job = mViewItemJobs.at( idx ); + bool newJobNeeded = true; - if ( job->currentPass() != ViewItemJob::Pass1Fill ) + // Try to attach to an existing fill job, if any. + // To enforce consistency we can attach only if the Fill job + // is the last one in the list (might be eventually *also* the first, + // and even being already processed but we must make sure that there + // aren't jobs _after_ it). + if ( jobCount > 0 ) { - // The job is a cleanup or in a later pass: the storage has been already accessed - // and the messages created... no need to care: we will invalidate the messages in a while. - continue; + ViewItemJob * job = mViewItemJobs.at( jobCount - 1 ); + if ( job->currentPass() == ViewItemJob::Pass1Fill ) + { + if ( + // The job ends just before the added rows + ( from == ( job->endIndex() + 1 ) ) && + // The job didn't reach the end of Pass1Fill yet + ( job->currentIndex() <= job->endIndex() ) + ) + { + // We can still attach this :) + job->setEndIndex( to ); + Q_ASSERT( job->currentIndex() <= job->endIndex() ); + newJobNeeded = false; + } + } } - if ( job->currentIndex() > job->endIndex() ) + if ( newJobNeeded ) { - // The job finished the Pass1Fill but still waits for the pass indicator to be - // changed. This is unlikely but still may happen if the job has been interrupted - // and then a call to slotStorageModelRowsRemoved() caused it to be forcibly completed. - continue; + // FIXME: Should take timing options from aggregation here ? + ViewItemJob * job = new ViewItemJob( from, to, 100, 50, 10 ); + mViewItemJobs.append( job ); } - // - // The following cases are possible: - // - // from to - // | | -> shift down job - // from to - // | | -> shift down and crop job - // from to - // | | -> kill job - // from to - // | | -> split job, crop and shift - // from to - // | | -> crop job - // from to - // | | -> job unaffected - // - // - // FOLDER - // |-------------------------|---------|--------------| - // 0 currentIndex endIndex count - // +-- job --+ - // + if ( !mFillStepTimer.isActive() ) + mFillStepTimer.start( mViewItemJobStepIdleInterval ); +} - if ( from > job->endIndex() ) - { - // The change is completely above the job, the job is not affected - continue; +void ModelPrivate::slotStorageModelRowsRemoved( const QModelIndex &parent, int from, int to ) +{ + // This is called when the underlying StorageModel emits the rowsRemoved signal. + + if ( parent.isValid() ) + return; // ugh... should never happen + + // look if no current job is in the middle + + Q_ASSERT( from <= to ); + + const int count = ( to - from ) + 1; + + int jobCount = mViewItemJobs.count(); + + if (mRootItem && from == 0 && count == mRootItem->childItemCount() && jobCount == 0) { + clear(); + return; } - if( from > job->currentIndex() ) // and from <= job->endIndex() + for ( int idx = 0; idx < jobCount; idx++ ) { - // The change starts in the middle of the job and ends in the middle or after the job. - // The first part is unaffected by the shift and ranges from job->currentIndex() to from - 1 - // We use the existing job for this. - job->setEndIndex( from - 1 ); // stop before the first removed row + ViewItemJob * job = mViewItemJobs.at( idx ); + + if ( job->currentPass() != ViewItemJob::Pass1Fill ) + { + // The job is a cleanup or in a later pass: the storage has been already accessed + // and the messages created... no need to care: we will invalidate the messages in a while. + continue; + } - Q_ASSERT( job->currentIndex() <= job->endIndex() ); + if ( job->currentIndex() > job->endIndex() ) + { + // The job finished the Pass1Fill but still waits for the pass indicator to be + // changed. This is unlikely but still may happen if the job has been interrupted + // and then a call to slotStorageModelRowsRemoved() caused it to be forcibly completed. + continue; + } - if ( to < job->endIndex() ) - { - // The change ends inside the job and a part of it can be completed. + // + // The following cases are possible: + // + // from to + // | | -> shift down job + // from to + // | | -> shift down and crop job + // from to + // | | -> kill job + // from to + // | | -> split job, crop and shift + // from to + // | | -> crop job + // from to + // | | -> job unaffected + // + // + // FOLDER + // |-------------------------|---------|--------------| + // 0 currentIndex endIndex count + // +-- job --+ + // - // We create a new job for the shifted remaining part. It would actually - // range from to + 1 up to job->endIndex(), but we need to shift it down by count. - // since count = ( to - from ) + 1 so from = to + 1 - count + if ( from > job->endIndex() ) + { + // The change is completely above the job, the job is not affected + continue; + } - ViewItemJob * newJob = new ViewItemJob( from, job->endIndex() - count, job->chunkTimeout(), job->idleInterval(), job->messageCheckCount() ); + if( from > job->currentIndex() ) // and from <= job->endIndex() + { + // The change starts in the middle of the job and ends in the middle or after the job. + // The first part is unaffected by the shift and ranges from job->currentIndex() to from - 1 + // We use the existing job for this. + job->setEndIndex( from - 1 ); // stop before the first removed row - Q_ASSERT( newJob->currentIndex() < newJob->endIndex() ); + Q_ASSERT( job->currentIndex() <= job->endIndex() ); - idx++; // we can skip this job in the loop, it's already ok - jobCount++; // and our range increases by one. - mViewItemJobs.insert( idx, newJob ); - } // else the change includes completely the end of the job and no other part of it can be completed. + if ( to < job->endIndex() ) + { + // The change ends inside the job and a part of it can be completed. - continue; - } + // We create a new job for the shifted remaining part. It would actually + // range from to + 1 up to job->endIndex(), but we need to shift it down by count. + // since count = ( to - from ) + 1 so from = to + 1 - count - // The change starts below (or exactly on the beginning of) the job. ( from <= job->currentIndex() ) - if ( to >= job->endIndex() ) - { - // The change completely covers the job: kill it + ViewItemJob * newJob = new ViewItemJob( from, job->endIndex() - count, job->chunkTimeout(), job->idleInterval(), job->messageCheckCount() ); - // We don't delete the job since we want the other passes to be completed - // This is because the Pass1Fill may have already filled mUnassignedMessageListForPass2 - // and may have set mOldestItem and mNewestItem. We *COULD* clear the unassigned - // message list with clearUnassignedMessageLists() but mOldestItem and mNewestItem - // could be still dangling pointers. So we just move the current index of the job - // after the end (so storage model scan terminates) and let it complete spontaneously. - job->setCurrentIndex( job->endIndex() + 1 ); + Q_ASSERT( newJob->currentIndex() < newJob->endIndex() ); - continue; - } + idx++; // we can skip this job in the loop, it's already ok + jobCount++; // and our range increases by one. + mViewItemJobs.insert( idx, newJob ); + } // else the change includes completely the end of the job and no other part of it can be completed. - if ( to >= job->currentIndex() ) - { - // The change partially covers the job. Only a part of it can be completed - // and it must be shifted down. It would actually - // range from to + 1 up to job->endIndex(), but we need to shift it down by count. - // since count = ( to - from ) + 1 so from = to + 1 - count - job->setCurrentIndex( from ); - job->setEndIndex( job->endIndex() - count ); + continue; + } - Q_ASSERT( job->currentIndex() <= job->endIndex() ); + // The change starts below (or exactly on the beginning of) the job. ( from <= job->currentIndex() ) + if ( to >= job->endIndex() ) + { + // The change completely covers the job: kill it - continue; - } + // We don't delete the job since we want the other passes to be completed + // This is because the Pass1Fill may have already filled mUnassignedMessageListForPass2 + // and may have set mOldestItem and mNewestItem. We *COULD* clear the unassigned + // message list with clearUnassignedMessageLists() but mOldestItem and mNewestItem + // could be still dangling pointers. So we just move the current index of the job + // after the end (so storage model scan terminates) and let it complete spontaneously. + job->setCurrentIndex( job->endIndex() + 1 ); - // The change is completely below the job: it must be shifted down. - job->setCurrentIndex( job->currentIndex() - count ); - job->setEndIndex( job->endIndex() - count ); - } + continue; + } - // This will invalidate the ModelInvariantIndex-es that have been removed and return - // them all in a nice list that we can feed to a view removal job. - QList< ModelInvariantIndex * > * invalidatedIndexes = mInvariantRowMapper->modelRowsRemoved( from, count ); + if ( to >= job->currentIndex() ) + { + // The change partially covers the job. Only a part of it can be completed + // and it must be shifted down. It would actually + // range from to + 1 up to job->endIndex(), but we need to shift it down by count. + // since count = ( to - from ) + 1 so from = to + 1 - count + job->setCurrentIndex( from ); + job->setEndIndex( job->endIndex() - count ); - if ( invalidatedIndexes ) - { - // Try to attach to an existing cleanup job, if any. - // To enforce consistency we can attach only if the Cleanup job - // is the last one in the list (might be eventually *also* the first, - // and even being already processed but we must make sure that there - // aren't jobs _after_ it). - if ( jobCount > 0 ) - { - ViewItemJob * job = mViewItemJobs.at( jobCount - 1 ); - if ( job->currentPass() == ViewItemJob::Pass1Cleanup ) - { - if ( ( job->currentIndex() <= job->endIndex() ) && job->invariantIndexList() ) - { - //kDebug() << "Appending " << invalidatedIndexes->count() << " invalidated indexes to existing cleanup job" << endl; - // We can still attach this :) - *( job->invariantIndexList() ) += *invalidatedIndexes; - job->setEndIndex( job->endIndex() + invalidatedIndexes->count() ); - delete invalidatedIndexes; - invalidatedIndexes = 0; + Q_ASSERT( job->currentIndex() <= job->endIndex() ); + + continue; } - } + + // The change is completely below the job: it must be shifted down. + job->setCurrentIndex( job->currentIndex() - count ); + job->setEndIndex( job->endIndex() - count ); } + // This will invalidate the ModelInvariantIndex-es that have been removed and return + // them all in a nice list that we can feed to a view removal job. + QList< ModelInvariantIndex * > * invalidatedIndexes = mInvariantRowMapper->modelRowsRemoved( from, count ); + if ( invalidatedIndexes ) { - // Didn't append to any existing cleanup job.. create a new one + // Try to attach to an existing cleanup job, if any. + // To enforce consistency we can attach only if the Cleanup job + // is the last one in the list (might be eventually *also* the first, + // and even being already processed but we must make sure that there + // aren't jobs _after_ it). + if ( jobCount > 0 ) + { + ViewItemJob * job = mViewItemJobs.at( jobCount - 1 ); + if ( job->currentPass() == ViewItemJob::Pass1Cleanup ) + { + if ( ( job->currentIndex() <= job->endIndex() ) && job->invariantIndexList() ) + { + //kDebug() << "Appending " << invalidatedIndexes->count() << " invalidated indexes to existing cleanup job" << endl; + // We can still attach this :) + *( job->invariantIndexList() ) += *invalidatedIndexes; + job->setEndIndex( job->endIndex() + invalidatedIndexes->count() ); + delete invalidatedIndexes; + invalidatedIndexes = 0; + } + } + } - //kDebug() << "Creating new cleanup job for " << invalidatedIndexes->count() << " invalidated indexes" << endl; - // FIXME: Should take timing options from aggregation here ? - ViewItemJob * job = new ViewItemJob( ViewItemJob::Pass1Cleanup, invalidatedIndexes, 100, 50, 10 ); - mViewItemJobs.append( job ); - } + if ( invalidatedIndexes ) + { + // Didn't append to any existing cleanup job.. create a new one - if ( !mFillStepTimer.isActive() ) - mFillStepTimer.start( mViewItemJobStepIdleInterval ); - } + //kDebug() << "Creating new cleanup job for " << invalidatedIndexes->count() << " invalidated indexes" << endl; + // FIXME: Should take timing options from aggregation here ? + ViewItemJob * job = new ViewItemJob( ViewItemJob::Pass1Cleanup, invalidatedIndexes, 100, 50, 10 ); + mViewItemJobs.append( job ); + } + + if ( !mFillStepTimer.isActive() ) + mFillStepTimer.start( mViewItemJobStepIdleInterval ); + } } void ModelPrivate::slotStorageModelLayoutChanged() { - kDebug() << "Storage model layout changed"; - // need to reset everything... - q->setStorageModel( mStorageModel ); - kDebug() << "Storage model layout changed done"; + kDebug() << "Storage model layout changed"; + // need to reset everything... + q->setStorageModel( mStorageModel ); + kDebug() << "Storage model layout changed done"; } void ModelPrivate::slotStorageModelDataChanged( const QModelIndex &fromIndex, const QModelIndex &toIndex ) { - Q_ASSERT( mStorageModel ); // must exist (and be the sender of the signal connected to this slot) + Q_ASSERT( mStorageModel ); // must exist (and be the sender of the signal connected to this slot) - int from = fromIndex.row(); - int to = toIndex.row(); + int from = fromIndex.row(); + int to = toIndex.row(); - Q_ASSERT( from <= to ); + Q_ASSERT( from <= to ); - int count = ( to - from ) + 1; + int count = ( to - from ) + 1; - int jobCount = mViewItemJobs.count(); + int jobCount = mViewItemJobs.count(); - // This will find out the ModelInvariantIndex-es that need an update and will return - // them all in a nice list that we can feed to a view removal job. - QList< ModelInvariantIndex * > * indexesThatNeedUpdate = mInvariantRowMapper->modelIndexRowRangeToModelInvariantIndexList( from, count ); + // This will find out the ModelInvariantIndex-es that need an update and will return + // them all in a nice list that we can feed to a view removal job. + QList< ModelInvariantIndex * > * indexesThatNeedUpdate = mInvariantRowMapper->modelIndexRowRangeToModelInvariantIndexList( from, count ); - if ( indexesThatNeedUpdate ) - { - // Try to attach to an existing update job, if any. - // To enforce consistency we can attach only if the Update job - // is the last one in the list (might be eventually *also* the first, - // and even being already processed but we must make sure that there - // aren't jobs _after_ it). - if ( jobCount > 0 ) + if ( indexesThatNeedUpdate ) { - ViewItemJob * job = mViewItemJobs.at( jobCount - 1 ); - if ( job->currentPass() == ViewItemJob::Pass1Update ) - { - if ( ( job->currentIndex() <= job->endIndex() ) && job->invariantIndexList() ) - { - // We can still attach this :) - *( job->invariantIndexList() ) += *indexesThatNeedUpdate; - job->setEndIndex( job->endIndex() + indexesThatNeedUpdate->count() ); - delete indexesThatNeedUpdate; - indexesThatNeedUpdate = 0; + // Try to attach to an existing update job, if any. + // To enforce consistency we can attach only if the Update job + // is the last one in the list (might be eventually *also* the first, + // and even being already processed but we must make sure that there + // aren't jobs _after_ it). + if ( jobCount > 0 ) + { + ViewItemJob * job = mViewItemJobs.at( jobCount - 1 ); + if ( job->currentPass() == ViewItemJob::Pass1Update ) + { + if ( ( job->currentIndex() <= job->endIndex() ) && job->invariantIndexList() ) + { + // We can still attach this :) + *( job->invariantIndexList() ) += *indexesThatNeedUpdate; + job->setEndIndex( job->endIndex() + indexesThatNeedUpdate->count() ); + delete indexesThatNeedUpdate; + indexesThatNeedUpdate = 0; + } + } } - } - } - if ( indexesThatNeedUpdate ) - { - // Didn't append to any existing update job.. create a new one - // FIXME: Should take timing options from aggregation here ? - ViewItemJob * job = new ViewItemJob( ViewItemJob::Pass1Update, indexesThatNeedUpdate, 100, 50, 10 ); - mViewItemJobs.append( job ); - } + if ( indexesThatNeedUpdate ) + { + // Didn't append to any existing update job.. create a new one + // FIXME: Should take timing options from aggregation here ? + ViewItemJob * job = new ViewItemJob( ViewItemJob::Pass1Update, indexesThatNeedUpdate, 100, 50, 10 ); + mViewItemJobs.append( job ); + } - if ( !mFillStepTimer.isActive() ) - mFillStepTimer.start( mViewItemJobStepIdleInterval ); - } + if ( !mFillStepTimer.isActive() ) + mFillStepTimer.start( mViewItemJobStepIdleInterval ); + } } void ModelPrivate::slotStorageModelHeaderDataChanged( Qt::Orientation, int, int ) { - if ( mStorageModelContainsOutboundMessages!=mStorageModel->containsOutboundMessages() ) { - mStorageModelContainsOutboundMessages = mStorageModel->containsOutboundMessages(); - emit q->headerDataChanged( Qt::Horizontal, 0, q->columnCount() ); - } + if ( mStorageModelContainsOutboundMessages!=mStorageModel->containsOutboundMessages() ) { + mStorageModelContainsOutboundMessages = mStorageModel->containsOutboundMessages(); + emit q->headerDataChanged( Qt::Horizontal, 0, q->columnCount() ); + } } Qt::ItemFlags Model::flags( const QModelIndex &index ) const { - if ( !index.isValid() ) - return Qt::NoItemFlags; + if ( !index.isValid() ) + return Qt::NoItemFlags; - Q_ASSERT( d->mModelForItemFunctions ); // UI must be connected if a valid index was queried + Q_ASSERT( d->mModelForItemFunctions ); // UI must be connected if a valid index was queried - Item * it = static_cast< Item * >( index.internalPointer() ); + Item * it = static_cast< Item * >( index.internalPointer() ); - Q_ASSERT( it ); + Q_ASSERT( it ); - if ( it->type() == Item::GroupHeader ) - return Qt::ItemIsEnabled; + if ( it->type() == Item::GroupHeader ) + return Qt::ItemIsEnabled; - Q_ASSERT( it->type() == Item::Message ); + Q_ASSERT( it->type() == Item::Message ); - if ( !static_cast< MessageItem * >( it )->isValid() ) - return Qt::NoItemFlags; // not enabled, not selectable + if ( !static_cast< MessageItem * >( it )->isValid() ) + return Qt::NoItemFlags; // not enabled, not selectable - if ( static_cast< MessageItem * >( it )->aboutToBeRemoved() ) - return Qt::NoItemFlags; // not enabled, not selectable + if ( static_cast< MessageItem * >( it )->aboutToBeRemoved() ) + return Qt::NoItemFlags; // not enabled, not selectable - if ( static_cast< MessageItem * >( it )->status().isDeleted() ) - return Qt::NoItemFlags; // not enabled, not selectable + if ( static_cast< MessageItem * >( it )->status().isDeleted() ) + return Qt::NoItemFlags; // not enabled, not selectable - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } QMimeData* MessageList::Core::Model::mimeData( const QModelIndexList& indexes ) const { - QList< MessageItem* > msgs; - foreach( const QModelIndex &idx, indexes ) { - if( idx.isValid() ) { - Item* item = static_cast< Item* >( idx.internalPointer() ); - if( item->type() == MessageList::Core::Item::Message ) { - msgs << static_cast< MessageItem* >( idx.internalPointer() ); + QList< MessageItem* > msgs; + foreach( const QModelIndex &idx, indexes ) { + if( idx.isValid() ) { + Item* item = static_cast< Item* >( idx.internalPointer() ); + if( item->type() == MessageList::Core::Item::Message ) { + msgs << static_cast< MessageItem* >( idx.internalPointer() ); + } } - } - } - return storageModel()->mimeData( msgs ); + } + return storageModel()->mimeData( msgs ); } Item *Model::rootItem() const { - return d->mRootItem; + return d->mRootItem; } bool Model::isLoading() const { - return d->mLoading; + return d->mLoading; } MessageItem * Model::messageItemByStorageRow( int row ) const { - if ( !d->mStorageModel ) - return 0; - ModelInvariantIndex * idx = d->mInvariantRowMapper->modelIndexRowToModelInvariantIndex( row ); - if ( !idx ) - return 0; + if ( !d->mStorageModel ) + return 0; + ModelInvariantIndex * idx = d->mInvariantRowMapper->modelIndexRowToModelInvariantIndex( row ); + if ( !idx ) + return 0; - return static_cast< MessageItem * >( idx ); + return static_cast< MessageItem * >( idx ); } MessageItemSetReference Model::createPersistentSet( const QList< MessageItem * > &items ) { - if ( !d->mPersistentSetManager ) - d->mPersistentSetManager = new MessageItemSetManager(); + if ( !d->mPersistentSetManager ) + d->mPersistentSetManager = new MessageItemSetManager(); - MessageItemSetReference ref = d->mPersistentSetManager->createSet(); - QList< MessageItem * >::ConstIterator end = items.constEnd(); - for ( QList< MessageItem * >::ConstIterator it = items.constBegin(); it != end; ++it ) - d->mPersistentSetManager->addMessageItem( ref, *it ); + MessageItemSetReference ref = d->mPersistentSetManager->createSet(); + QList< MessageItem * >::ConstIterator end = items.constEnd(); + for ( QList< MessageItem * >::ConstIterator it = items.constBegin(); it != end; ++it ) + d->mPersistentSetManager->addMessageItem( ref, *it ); - return ref; + return ref; } QList< MessageItem * > Model::persistentSetCurrentMessageItemList( MessageItemSetReference ref ) { - if ( d->mPersistentSetManager ) - return d->mPersistentSetManager->messageItems( ref ); - return QList< MessageItem * >(); + if ( d->mPersistentSetManager ) + return d->mPersistentSetManager->messageItems( ref ); + return QList< MessageItem * >(); } void Model::deletePersistentSet( MessageItemSetReference ref ) { - if ( !d->mPersistentSetManager ) - return; + if ( !d->mPersistentSetManager ) + return; - d->mPersistentSetManager->removeSet( ref ); + d->mPersistentSetManager->removeSet( ref ); - if ( d->mPersistentSetManager->setCount() < 1 ) - { - delete d->mPersistentSetManager; - d->mPersistentSetManager = 0; - } + if ( d->mPersistentSetManager->setCount() < 1 ) + { + delete d->mPersistentSetManager; + d->mPersistentSetManager = 0; + } } #include "moc_model.cpp" diff -Nru kdepim-4.12.97/messagelist/core/model.h kdepim-4.13.0/messagelist/core/model.h --- kdepim-4.12.97/messagelist/core/model.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/model.h 2014-04-10 07:40:20.000000000 +0000 @@ -76,28 +76,28 @@ */ class MESSAGELIST_EXPORT Model : public QAbstractItemModel { - friend class Item; - friend class ItemPrivate; + friend class Item; + friend class ItemPrivate; - Q_OBJECT + Q_OBJECT public: - /** + /** * Creates the mighty Model attached to the specified View. */ - explicit Model( View *pParent ); + explicit Model( View *pParent ); - /** + /** * Destroys the mighty model along with the tree of items it manages. */ - ~Model(); + ~Model(); - /** + /** * Returns the StorageModel currently set. */ - StorageModel *storageModel() const; + StorageModel *storageModel() const; - /** + /** * Sets the storage model from that the messages to be displayed should be fetched. * The model is then reset and a new fill operation is started. The fill operation may * or may not complete before setStorageModel() returns. This depends on the fill @@ -112,75 +112,75 @@ * and pre-selecting would confuse him). The pre-selection is applied once * loading is complete. */ - void setStorageModel( StorageModel *storageModel, PreSelectionMode preSelectionMode = PreSelectLastSelected ); + void setStorageModel( StorageModel *storageModel, PreSelectionMode preSelectionMode = PreSelectLastSelected ); - /** + /** * Sets the pre-selection mode. * * Called with PreSelectNone to abort any pending message pre-selection. This may be done if the user * starts navigating the view and selecting items before we actually could * apply the pre-selection. */ - void setPreSelectionMode( PreSelectionMode preSelect ); + void setPreSelectionMode( PreSelectionMode preSelect ); - /** + /** * Returns the hidden root item that all the messages are (or will be) attached to. * The returned value is never 0. */ - Item *rootItem() const; + Item *rootItem() const; - /** + /** * Returns true if the view is currently loading, that is * it's in the first (possibly lenghty) job batch after attacching to a StorageModel. */ - bool isLoading() const; + bool isLoading() const; - /** + /** * Returns the message item that is at the _current_ storage row index * or zero if no such storage item is found. Please note that this may return 0 * also if the specified storage row hasn't been actually read yet. This may happen * if isLoading() returns true. In this case the only thing you can do is to retry in a while. */ - MessageItem * messageItemByStorageRow( int row ) const; + MessageItem * messageItemByStorageRow( int row ) const; - /** + /** * Sets the Aggregation mode. * Does not reload the model in any way: you need to call setStorageModel( storageModel() ) for this to happen. * The pointer ownership remains of the caller which must ensure its validity until the next * call to setAggretation() or until this Model dies. The caller, in fact, is Widget which * takes care of meeting the above conditions. The aggregation pointer must not be null. */ - void setAggregation( const Aggregation * aggregation ); + void setAggregation( const Aggregation * aggregation ); - /** + /** * Sets the Theme. * Does not reload the model in any way: you need to call setStorageModel( storageModel() ) for this to happen. * The pointer ownership remains of the caller which must ensure its validity until the next * call to setTheme() or until this Model dies. The caller, in fact, is Widget which * takes care of meeting the above conditions. The theme pointer must not be null. */ - void setTheme( const Theme * theme ); + void setTheme( const Theme * theme ); - /** + /** * Sets the sort order. As with setTheme() and setAggregation(), this does not reload the * model in any way. */ - void setSortOrder( const SortOrder * sortOrder ); + void setSortOrder( const SortOrder * sortOrder ); - /** + /** * Returns the sort order */ - const SortOrder * sortOrder() const; + const SortOrder * sortOrder() const; - /** + /** * Sets the Filter to be applied on messages. filter may be null (no filter is applied). * The pointer ownership remains of the caller which must ensure its validity until the next * call to setFilter() or until this Model dies. The caller, in fact, is Widget which * takes care of meeting the above conditions. The Filter pointer may be null. */ - void setFilter( const Filter *filter ); + void setFilter( const Filter *filter ); - /** + /** * Creates a persistent set for the specified MessageItems and * returns its reference. Later you can use this reference * to retrieve the list of MessageItems that are still valid. @@ -190,56 +190,56 @@ * while manipulating the view) so be sure to call deletePersistentSet() * when you no longer need it. */ - MessageItemSetReference createPersistentSet( const QList< MessageItem * > &items ); + MessageItemSetReference createPersistentSet( const QList< MessageItem * > &items ); - /** + /** * Returns the list of MessageItems that are still existing in the * set pointed by the specified reference. This list will contain * at most the messages that you have passed to createPersistentSet() * but may contain less (even 0) if these MessageItem object were removed * from the view for some reason. */ - QList< MessageItem * > persistentSetCurrentMessageItemList( MessageItemSetReference ref ); + QList< MessageItem * > persistentSetCurrentMessageItemList( MessageItemSetReference ref ); - /** + /** * Deletes the persistent set pointed by the specified reference. * If the set does not exist anymore, nothing happens. */ - void deletePersistentSet( MessageItemSetReference ref ); + void deletePersistentSet( MessageItemSetReference ref ); - // Mandatory QAbstractItemModel interface. + // Mandatory QAbstractItemModel interface. - virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const; - virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; - virtual QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const; - QModelIndex index( Item *item, int column ) const; - virtual QModelIndex parent( const QModelIndex &index ) const; - virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const; - virtual Qt::ItemFlags flags( const QModelIndex &index ) const; + virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const; + virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; + virtual QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const; + QModelIndex index( Item *item, int column ) const; + virtual QModelIndex parent( const QModelIndex &index ) const; + virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const; + virtual Qt::ItemFlags flags( const QModelIndex &index ) const; - /// Called when user initiates a drag from the messagelist - virtual QMimeData* mimeData( const QModelIndexList& indexes ) const; + /// Called when user initiates a drag from the messagelist + virtual QMimeData* mimeData( const QModelIndexList& indexes ) const; Q_SIGNALS: - /** + /** * Notify the outside when updating the status bar with a message * could be useful */ - void statusMessage( const QString &message ); + void statusMessage( const QString &message ); private: - Q_PRIVATE_SLOT(d, void checkIfDateChanged()) - Q_PRIVATE_SLOT(d, void viewItemJobStep()) - Q_PRIVATE_SLOT(d, void slotStorageModelRowsInserted( const QModelIndex &, int, int )) - Q_PRIVATE_SLOT(d, void slotStorageModelRowsRemoved( const QModelIndex &, int, int )) - Q_PRIVATE_SLOT(d, void slotStorageModelDataChanged( const QModelIndex &, const QModelIndex & )) - Q_PRIVATE_SLOT(d, void slotStorageModelHeaderDataChanged( Qt::Orientation, int, int )) - Q_PRIVATE_SLOT(d, void slotStorageModelLayoutChanged()) - Q_PRIVATE_SLOT(d, void slotApplyFilter()) + Q_PRIVATE_SLOT(d, void checkIfDateChanged()) + Q_PRIVATE_SLOT(d, void viewItemJobStep()) + Q_PRIVATE_SLOT(d, void slotStorageModelRowsInserted( const QModelIndex &, int, int )) + Q_PRIVATE_SLOT(d, void slotStorageModelRowsRemoved( const QModelIndex &, int, int )) + Q_PRIVATE_SLOT(d, void slotStorageModelDataChanged( const QModelIndex &, const QModelIndex & )) + Q_PRIVATE_SLOT(d, void slotStorageModelHeaderDataChanged( Qt::Orientation, int, int )) + Q_PRIVATE_SLOT(d, void slotStorageModelLayoutChanged()) + Q_PRIVATE_SLOT(d, void slotApplyFilter()) - friend class ModelPrivate; - ModelPrivate * const d; + friend class ModelPrivate; + ModelPrivate * const d; }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/modelinvariantindex.cpp kdepim-4.13.0/messagelist/core/modelinvariantindex.cpp --- kdepim-4.12.97/messagelist/core/modelinvariantindex.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/modelinvariantindex.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -26,27 +26,27 @@ using namespace MessageList::Core; ModelInvariantIndex::ModelInvariantIndex() - : d( new Private ) + : d( new Private ) { - d->mRowMapper = 0; + d->mRowMapper = 0; } ModelInvariantIndex::~ModelInvariantIndex() { - if ( d->mRowMapper ) - d->mRowMapper->d->indexDead( this ); + if ( d->mRowMapper ) + d->mRowMapper->d->indexDead( this ); - delete d; + delete d; } bool ModelInvariantIndex::isValid() const { - return d->mRowMapper != 0; + return d->mRowMapper != 0; } int ModelInvariantIndex::currentModelIndexRow() { - if ( d->mRowMapper ) - return d->mRowMapper->modelInvariantIndexToModelIndexRow( this ); - return -1; + if ( d->mRowMapper ) + return d->mRowMapper->modelInvariantIndexToModelIndexRow( this ); + return -1; } diff -Nru kdepim-4.12.97/messagelist/core/modelinvariantindex.h kdepim-4.13.0/messagelist/core/modelinvariantindex.h --- kdepim-4.12.97/messagelist/core/modelinvariantindex.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/modelinvariantindex.h 2014-04-10 07:40:20.000000000 +0000 @@ -43,23 +43,23 @@ */ class MESSAGELIST_EXPORT ModelInvariantIndex { - friend class ModelInvariantRowMapper; - friend class ModelInvariantRowMapperPrivate; - friend class RowShift; + friend class ModelInvariantRowMapper; + friend class ModelInvariantRowMapperPrivate; + friend class RowShift; public: - explicit ModelInvariantIndex(); - virtual ~ModelInvariantIndex(); + explicit ModelInvariantIndex(); + virtual ~ModelInvariantIndex(); public: - /** + /** * Returns true if this ModelInvariantIndex is valid, that is, it has been attacched * to a ModelInvariantRowMapper. Returns false otherwise. * An invalid index will always map to the current row -1 (which is invalid as QModelIndex row). */ - bool isValid() const; + bool isValid() const; - /** + /** * Returns the current model index row for this invariant index. This function * calls the mapper and asks it to perform the persistent mapping. * If this index isn't valid then the returned value is -1. @@ -68,11 +68,11 @@ * by calling the modelInvariantIndexToModelIndexRow() by your own. If you don't * own the mapper then this function is the only way to go. */ - int currentModelIndexRow(); + int currentModelIndexRow(); private: - class Private; - Private * const d; + class Private; + Private * const d; }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/modelinvariantrowmapper.cpp kdepim-4.13.0/messagelist/core/modelinvariantrowmapper.cpp --- kdepim-4.12.97/messagelist/core/modelinvariantrowmapper.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/modelinvariantrowmapper.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -36,23 +36,23 @@ class RowShift { public: - int mMinimumRowIndex; - int mShift; - QHash< int, ModelInvariantIndex * > * mInvariantHash; + int mMinimumRowIndex; + int mShift; + QHash< int, ModelInvariantIndex * > * mInvariantHash; public: - RowShift( int minRowIndex, int shift, QHash< int, ModelInvariantIndex * > * invariantHash ) - : mMinimumRowIndex( minRowIndex ), mShift( shift ), mInvariantHash( invariantHash ) - { - } - - ~RowShift() - { - QHash< int, ModelInvariantIndex * >::ConstIterator end( mInvariantHash->constEnd() ); - for ( QHash< int, ModelInvariantIndex * >::ConstIterator it = mInvariantHash->constBegin(); it != end; ++it ) - ( *it )->d->setRowMapper( 0 ); - delete mInvariantHash; - } + RowShift( int minRowIndex, int shift, QHash< int, ModelInvariantIndex * > * invariantHash ) + : mMinimumRowIndex( minRowIndex ), mShift( shift ), mInvariantHash( invariantHash ) + { + } + + ~RowShift() + { + QHash< int, ModelInvariantIndex * >::ConstIterator end( mInvariantHash->constEnd() ); + for ( QHash< int, ModelInvariantIndex * >::ConstIterator it = mInvariantHash->constBegin(); it != end; ++it ) + ( *it )->d->setRowMapper( 0 ); + delete mInvariantHash; + } }; } // namespace Core @@ -62,614 +62,614 @@ using namespace MessageList::Core; ModelInvariantRowMapper::ModelInvariantRowMapper() - : d( new ModelInvariantRowMapperPrivate( this ) ) + : d( new ModelInvariantRowMapperPrivate( this ) ) { - d->mRowShiftList = new QList< RowShift * >(); - d->mCurrentShiftSerial = 0; - d->mCurrentInvariantHash = new QHash< int, ModelInvariantIndex * >(); - d->mUpdateTimer = new QTimer( this ); - d->mUpdateTimer->setSingleShot( true ); - d->mLazyUpdateChunkInterval = 50; - d->mLazyUpdateIdleInterval = 50; + d->mRowShiftList = new QList< RowShift * >(); + d->mCurrentShiftSerial = 0; + d->mCurrentInvariantHash = new QHash< int, ModelInvariantIndex * >(); + d->mUpdateTimer = new QTimer( this ); + d->mUpdateTimer->setSingleShot( true ); + d->mLazyUpdateChunkInterval = 50; + d->mLazyUpdateIdleInterval = 50; - connect( d->mUpdateTimer, SIGNAL(timeout()), - SLOT(slotPerformLazyUpdate()) ); + connect( d->mUpdateTimer, SIGNAL(timeout()), + SLOT(slotPerformLazyUpdate()) ); } ModelInvariantRowMapper::~ModelInvariantRowMapper() { - if ( d->mUpdateTimer->isActive() ) - d->mUpdateTimer->stop(); + if ( d->mUpdateTimer->isActive() ) + d->mUpdateTimer->stop(); - // FIXME: optimize this (it CAN be optimized) - QHash< int, ModelInvariantIndex * >::ConstIterator end( d->mCurrentInvariantHash->constEnd() ); - for ( QHash< int, ModelInvariantIndex * >::ConstIterator it = d->mCurrentInvariantHash->constBegin(); it != end; ++it ) - ( *it )->d->setRowMapper( 0 ); - delete d->mCurrentInvariantHash; - - if ( d->mRowShiftList ) - { - while ( !d->mRowShiftList->isEmpty() ) - delete d->mRowShiftList->takeFirst(); + // FIXME: optimize this (it CAN be optimized) + QHash< int, ModelInvariantIndex * >::ConstIterator end( d->mCurrentInvariantHash->constEnd() ); + for ( QHash< int, ModelInvariantIndex * >::ConstIterator it = d->mCurrentInvariantHash->constBegin(); it != end; ++it ) + ( *it )->d->setRowMapper( 0 ); + delete d->mCurrentInvariantHash; - delete d->mRowShiftList; - } + if ( d->mRowShiftList ) + { + while ( !d->mRowShiftList->isEmpty() ) + delete d->mRowShiftList->takeFirst(); + + delete d->mRowShiftList; + } - delete d; + delete d; } void ModelInvariantRowMapperPrivate::killFirstRowShift() { - RowShift * shift = mRowShiftList->at( 0 ); + RowShift * shift = mRowShiftList->at( 0 ); - Q_ASSERT( shift->mInvariantHash->isEmpty() ); + Q_ASSERT( shift->mInvariantHash->isEmpty() ); - delete shift; - mRowShiftList->removeAt( 0 ); - mRemovedShiftCount++; - if ( mRowShiftList->isEmpty() ) - { - delete mRowShiftList; - mRowShiftList = 0; - } + delete shift; + mRowShiftList->removeAt( 0 ); + mRemovedShiftCount++; + if ( mRowShiftList->isEmpty() ) + { + delete mRowShiftList; + mRowShiftList = 0; + } } void ModelInvariantRowMapperPrivate::indexDead( ModelInvariantIndex * invariant ) { - Q_ASSERT( invariant->d->rowMapper() == q ); + Q_ASSERT( invariant->d->rowMapper() == q ); - if ( invariant->d->rowMapperSerial() == mCurrentShiftSerial ) - { - mCurrentInvariantHash->remove( invariant->d->modelIndexRow() ); - return; - } + if ( invariant->d->rowMapperSerial() == mCurrentShiftSerial ) + { + mCurrentInvariantHash->remove( invariant->d->modelIndexRow() ); + return; + } - Q_ASSERT( invariant->d->rowMapperSerial() < mCurrentShiftSerial ); + Q_ASSERT( invariant->d->rowMapperSerial() < mCurrentShiftSerial ); - if ( !mRowShiftList ) { - return; // not found (not requested yet or invalid index at all) - } + if ( !mRowShiftList ) { + return; // not found (not requested yet or invalid index at all) + } - uint invariantShiftIndex = invariant->d->rowMapperSerial() - mRemovedShiftCount; + uint invariantShiftIndex = invariant->d->rowMapperSerial() - mRemovedShiftCount; - Q_ASSERT( invariantShiftIndex < static_cast< uint >( mRowShiftList->count() ) ); + Q_ASSERT( invariantShiftIndex < static_cast< uint >( mRowShiftList->count() ) ); - RowShift * shift = mRowShiftList->at( invariantShiftIndex ); + RowShift * shift = mRowShiftList->at( invariantShiftIndex ); - Q_ASSERT( shift ); + Q_ASSERT( shift ); - shift->mInvariantHash->remove( invariant->d->modelIndexRow() ); + shift->mInvariantHash->remove( invariant->d->modelIndexRow() ); - if ( ( shift->mInvariantHash->isEmpty() ) && ( invariantShiftIndex == 0 ) ) - { - // no more invariants with serial <= invariant->d->rowMapperSerial() - killFirstRowShift(); - } + if ( ( shift->mInvariantHash->isEmpty() ) && ( invariantShiftIndex == 0 ) ) + { + // no more invariants with serial <= invariant->d->rowMapperSerial() + killFirstRowShift(); + } } void ModelInvariantRowMapperPrivate::updateModelInvariantIndex( int modelIndexRow, ModelInvariantIndex * invariantToFill ) { - // Here the invariant already belongs to this mapper. We ASSUME that it's somewhere - // in the history and not in the hash belonging to the current serial. - // modelIndexRow is the CURRENT model index row. - Q_ASSERT( invariantToFill->d->rowMapper() == q ); + // Here the invariant already belongs to this mapper. We ASSUME that it's somewhere + // in the history and not in the hash belonging to the current serial. + // modelIndexRow is the CURRENT model index row. + Q_ASSERT( invariantToFill->d->rowMapper() == q ); - uint invariantShiftIndex = invariantToFill->d->rowMapperSerial() - mRemovedShiftCount; + uint invariantShiftIndex = invariantToFill->d->rowMapperSerial() - mRemovedShiftCount; - Q_ASSERT( invariantShiftIndex < static_cast< uint >( mRowShiftList->count() ) ); + Q_ASSERT( invariantShiftIndex < static_cast< uint >( mRowShiftList->count() ) ); - RowShift * shift = mRowShiftList->at( invariantShiftIndex ); + RowShift * shift = mRowShiftList->at( invariantShiftIndex ); - int count = shift->mInvariantHash->remove( invariantToFill->d->modelIndexRow() ); + int count = shift->mInvariantHash->remove( invariantToFill->d->modelIndexRow() ); - Q_ASSERT( count > 0 ); - Q_UNUSED( count ); + Q_ASSERT( count > 0 ); + Q_UNUSED( count ); - // update and make it belong to the current serial - invariantToFill->d->setModelIndexRowAndRowMapperSerial( modelIndexRow, mCurrentShiftSerial ); + // update and make it belong to the current serial + invariantToFill->d->setModelIndexRowAndRowMapperSerial( modelIndexRow, mCurrentShiftSerial ); - Q_ASSERT( !mCurrentInvariantHash->contains( invariantToFill->d->modelIndexRow() ) ); + Q_ASSERT( !mCurrentInvariantHash->contains( invariantToFill->d->modelIndexRow() ) ); - mCurrentInvariantHash->insert( invariantToFill->d->modelIndexRow(), invariantToFill ); + mCurrentInvariantHash->insert( invariantToFill->d->modelIndexRow(), invariantToFill ); - if ( ( shift->mInvariantHash->isEmpty() ) && ( invariantShiftIndex == 0 ) ) - { - // no more invariants with serial <= invariantToFill->rowMapperSerial() - killFirstRowShift(); - } + if ( ( shift->mInvariantHash->isEmpty() ) && ( invariantShiftIndex == 0 ) ) + { + // no more invariants with serial <= invariantToFill->rowMapperSerial() + killFirstRowShift(); + } } ModelInvariantIndex * ModelInvariantRowMapperPrivate::modelIndexRowToModelInvariantIndexInternal( int modelIndexRow, bool updateIfNeeded ) { - // First of all look it up in the current hash - ModelInvariantIndex * invariant = mCurrentInvariantHash->value( modelIndexRow, 0 ); - if ( invariant ) - return invariant; // found: was up to date - - // Go backward in history by unapplying changes - if ( !mRowShiftList ) - return 0; // not found (not requested yet or invalid index at all) - - int idx = mRowShiftList->count(); - if ( idx == 0 ) - { - Q_ASSERT( false ); - return 0; // should never happen (mRowShiftList should have been 0), but well... - } - idx--; - - int previousIndexRow = modelIndexRow; - - while ( idx >= 0 ) - { - RowShift * shift = mRowShiftList->at( idx ); - - // this shift has taken "previousModelIndexRow" in the historic state - // and has executed: - // - // if ( previousIndexRow >= shift->mMinimumRowIndex ) - // previousIndexRow += shift->mShift; - // - // so inverting it - // - // int potentialPreviousModelIndexRow = modelIndexRow - shift->mShift; - // if ( potentialPreviousModelIndexRow >= shift->mMinimumRowIndex ) - // previousIndexRow = potentialPreviousModelIndexRow; - // - // or by simplyfying... + // First of all look it up in the current hash + ModelInvariantIndex * invariant = mCurrentInvariantHash->value( modelIndexRow, 0 ); + if ( invariant ) + return invariant; // found: was up to date - int potentialPreviousModelIndexRow = previousIndexRow - shift->mShift; - if ( potentialPreviousModelIndexRow >= shift->mMinimumRowIndex ) - previousIndexRow = potentialPreviousModelIndexRow; + // Go backward in history by unapplying changes + if ( !mRowShiftList ) + return 0; // not found (not requested yet or invalid index at all) - invariant = shift->mInvariantHash->value( previousIndexRow, 0 ); - if ( invariant ) + int idx = mRowShiftList->count(); + if ( idx == 0 ) { - // found at this level in history - if ( updateIfNeeded ) // update it too - updateModelInvariantIndex( modelIndexRow, invariant ); - return invariant; + Q_ASSERT( false ); + return 0; // should never happen (mRowShiftList should have been 0), but well... } - idx--; - } - kWarning() << "Requested invariant for storage row index " - << modelIndexRow << " not found in history"; - return 0; // not found in history + int previousIndexRow = modelIndexRow; + + while ( idx >= 0 ) + { + RowShift * shift = mRowShiftList->at( idx ); + + // this shift has taken "previousModelIndexRow" in the historic state + // and has executed: + // + // if ( previousIndexRow >= shift->mMinimumRowIndex ) + // previousIndexRow += shift->mShift; + // + // so inverting it + // + // int potentialPreviousModelIndexRow = modelIndexRow - shift->mShift; + // if ( potentialPreviousModelIndexRow >= shift->mMinimumRowIndex ) + // previousIndexRow = potentialPreviousModelIndexRow; + // + // or by simplyfying... + + int potentialPreviousModelIndexRow = previousIndexRow - shift->mShift; + if ( potentialPreviousModelIndexRow >= shift->mMinimumRowIndex ) + previousIndexRow = potentialPreviousModelIndexRow; + + invariant = shift->mInvariantHash->value( previousIndexRow, 0 ); + if ( invariant ) + { + // found at this level in history + if ( updateIfNeeded ) // update it too + updateModelInvariantIndex( modelIndexRow, invariant ); + return invariant; + } + + idx--; + } + + kWarning() << "Requested invariant for storage row index " + << modelIndexRow << " not found in history"; + return 0; // not found in history } void ModelInvariantRowMapper::setLazyUpdateChunkInterval( int chunkInterval ) { - d->mLazyUpdateChunkInterval = chunkInterval; + d->mLazyUpdateChunkInterval = chunkInterval; } void ModelInvariantRowMapper::setLazyUpdateIdleInterval( int idleInterval ) { - d->mLazyUpdateIdleInterval = idleInterval; + d->mLazyUpdateIdleInterval = idleInterval; } int ModelInvariantRowMapper::modelInvariantIndexToModelIndexRow( ModelInvariantIndex * invariant ) { - // the invariant shift serial is the serial this mapper - // had at the time it emitted the invariant. - // mRowShiftList at that time had at most invariantShiftSerial items. - Q_ASSERT( invariant ); - - if ( invariant->d->rowMapper() != this ) - return -1; - - if ( invariant->d->rowMapperSerial() == d->mCurrentShiftSerial ) - { - Q_ASSERT( d->mCurrentInvariantHash->value( invariant->d->modelIndexRow() ) == invariant ); - return invariant->d->modelIndexRow(); // this invariant was emitted very recently and isn't affected by any change - } - - // If RowShift elements weren't removed from the list then - // we should have mCurrentShiftSerial items in the list. - // But RowShifts ARE removed sequentially from the beginning of the list - // as the invariants are updated in the user's data. - // We are making sure that if a RowShift belonging to a certain - // serial is removed from the list then there are no more - // ModelInvariantIndexinstances with that (or a lower) serial around. - // Thus invariantShiftSerial is >= mRemovedShiftCount. - - // Example: - // Initial state, no shifts, current serial 0, removed shifts 0 - // Emit ModelInvariantIndexfor model index row 6, with serial 0. - // User asks for model index row of invariant that has row index 10 and serial 0. - // The serial is equal to the current serial and we return the row index unchanged. - // A row arrives at position 4 - // We add a RowShift with start index 5 and offset +1 - // We increase current serial to 1 - // User asks for model index row of invariant that has row index 6 with serial 0. - // We compute the first RowShift index as serial 0 - removed 0 = 0 - // We apply the row shifts starting at that index. - // That is, since the requested row index is 6 >= 5 - // We apply +1 shift and return row index 7 serial 1 - // User asks for model index row of invariant that has row index 7 with serial 1 - // The serial is equal to the current serial and we return the row index unchanged still with serial 1 - // We update all the invariants in the user's data so that - // there are no more invariants with serial 0. - // We remove the RowShift and increase removed shift count to 1 - // User asks for model index row of invariant that has row index 7 - // The ModelInvariantIndex MUST have at least serial 1 because of the removal step above. - // The serial is equal to the current serial and we return the row index unchanged still with serial 1 - // A row arrives at position 2 - // We add a RowShift with start index 3 and offset +1 - // We increase current serial to 2 - // User asks for model index row of invariant that has row index 7 with serial 1. - // We compute the first RowShift index as serial 1 - removed 1 = 0 - // We apply the row shifts starting at that index. - // That is, since the requested row index is 7 >= 3 - // We apply +1 shift and return row index 8 serial 2 - // User asks for model index row of invariant that has row index 8 and serial 2 - // The serial is equal to the current serial and we return the row index unchanged still with serial 2 - // Etc... - - // So if we can trust that the user doesn't mess up with serials - // and the requested serial is not equal to the current serial - // then we can be 100% sure that mRowShiftList is not null (it contains at least one item). - // The requested serial is surely >= than mRemovedShiftCount too. - - // To find the starting index of the RowShifts that apply to this - // serial we need to offset them by the removed rows. - - uint invariantShiftIndex = invariant->d->rowMapperSerial() - d->mRemovedShiftCount; - - Q_ASSERT( d->mRowShiftList ); - - // For the reasoning above invariantShiftIndex is surely < than mRowShiftList.count() - - const uint count = static_cast< uint >( d->mRowShiftList->count() ); - - Q_ASSERT( invariantShiftIndex < count ); - - int modelIndexRow = invariant->d->modelIndexRow(); - - // apply shifts - for ( uint idx = invariantShiftIndex; idx < count; idx++ ) - { - RowShift * shift = d->mRowShiftList->at( idx ); - if ( modelIndexRow >= shift->mMinimumRowIndex ) - modelIndexRow += shift->mShift; - } + // the invariant shift serial is the serial this mapper + // had at the time it emitted the invariant. + // mRowShiftList at that time had at most invariantShiftSerial items. + Q_ASSERT( invariant ); - // Update the invariant on-the-fly too... - d->updateModelInvariantIndex( modelIndexRow, invariant ); + if ( invariant->d->rowMapper() != this ) + return -1; + + if ( invariant->d->rowMapperSerial() == d->mCurrentShiftSerial ) + { + Q_ASSERT( d->mCurrentInvariantHash->value( invariant->d->modelIndexRow() ) == invariant ); + return invariant->d->modelIndexRow(); // this invariant was emitted very recently and isn't affected by any change + } - return modelIndexRow; + // If RowShift elements weren't removed from the list then + // we should have mCurrentShiftSerial items in the list. + // But RowShifts ARE removed sequentially from the beginning of the list + // as the invariants are updated in the user's data. + // We are making sure that if a RowShift belonging to a certain + // serial is removed from the list then there are no more + // ModelInvariantIndexinstances with that (or a lower) serial around. + // Thus invariantShiftSerial is >= mRemovedShiftCount. + + // Example: + // Initial state, no shifts, current serial 0, removed shifts 0 + // Emit ModelInvariantIndexfor model index row 6, with serial 0. + // User asks for model index row of invariant that has row index 10 and serial 0. + // The serial is equal to the current serial and we return the row index unchanged. + // A row arrives at position 4 + // We add a RowShift with start index 5 and offset +1 + // We increase current serial to 1 + // User asks for model index row of invariant that has row index 6 with serial 0. + // We compute the first RowShift index as serial 0 - removed 0 = 0 + // We apply the row shifts starting at that index. + // That is, since the requested row index is 6 >= 5 + // We apply +1 shift and return row index 7 serial 1 + // User asks for model index row of invariant that has row index 7 with serial 1 + // The serial is equal to the current serial and we return the row index unchanged still with serial 1 + // We update all the invariants in the user's data so that + // there are no more invariants with serial 0. + // We remove the RowShift and increase removed shift count to 1 + // User asks for model index row of invariant that has row index 7 + // The ModelInvariantIndex MUST have at least serial 1 because of the removal step above. + // The serial is equal to the current serial and we return the row index unchanged still with serial 1 + // A row arrives at position 2 + // We add a RowShift with start index 3 and offset +1 + // We increase current serial to 2 + // User asks for model index row of invariant that has row index 7 with serial 1. + // We compute the first RowShift index as serial 1 - removed 1 = 0 + // We apply the row shifts starting at that index. + // That is, since the requested row index is 7 >= 3 + // We apply +1 shift and return row index 8 serial 2 + // User asks for model index row of invariant that has row index 8 and serial 2 + // The serial is equal to the current serial and we return the row index unchanged still with serial 2 + // Etc... + + // So if we can trust that the user doesn't mess up with serials + // and the requested serial is not equal to the current serial + // then we can be 100% sure that mRowShiftList is not null (it contains at least one item). + // The requested serial is surely >= than mRemovedShiftCount too. + + // To find the starting index of the RowShifts that apply to this + // serial we need to offset them by the removed rows. + + uint invariantShiftIndex = invariant->d->rowMapperSerial() - d->mRemovedShiftCount; + + Q_ASSERT( d->mRowShiftList ); + + // For the reasoning above invariantShiftIndex is surely < than mRowShiftList.count() + + const uint count = static_cast< uint >( d->mRowShiftList->count() ); + + Q_ASSERT( invariantShiftIndex < count ); + + int modelIndexRow = invariant->d->modelIndexRow(); + + // apply shifts + for ( uint idx = invariantShiftIndex; idx < count; idx++ ) + { + RowShift * shift = d->mRowShiftList->at( idx ); + if ( modelIndexRow >= shift->mMinimumRowIndex ) + modelIndexRow += shift->mShift; + } + + // Update the invariant on-the-fly too... + d->updateModelInvariantIndex( modelIndexRow, invariant ); + + return modelIndexRow; } void ModelInvariantRowMapper::createModelInvariantIndex( int modelIndexRow, ModelInvariantIndex * invariantToFill ) { - // The user is athemeg for the invariant of the item that is at the CURRENT modelIndexRow. - Q_ASSERT( invariantToFill->d->rowMapper() == 0 ); + // The user is athemeg for the invariant of the item that is at the CURRENT modelIndexRow. + Q_ASSERT( invariantToFill->d->rowMapper() == 0 ); - // Plain new invariant. Fill it and add to the current hash. - invariantToFill->d->setModelIndexRowAndRowMapperSerial( modelIndexRow, d->mCurrentShiftSerial ); - invariantToFill->d->setRowMapper( this ); + // Plain new invariant. Fill it and add to the current hash. + invariantToFill->d->setModelIndexRowAndRowMapperSerial( modelIndexRow, d->mCurrentShiftSerial ); + invariantToFill->d->setRowMapper( this ); - Q_ASSERT( !d->mCurrentInvariantHash->contains( modelIndexRow ) ); + Q_ASSERT( !d->mCurrentInvariantHash->contains( modelIndexRow ) ); - d->mCurrentInvariantHash->insert( modelIndexRow, invariantToFill ); + d->mCurrentInvariantHash->insert( modelIndexRow, invariantToFill ); } ModelInvariantIndex *ModelInvariantRowMapper::modelIndexRowToModelInvariantIndex( int modelIndexRow ) { - return d->modelIndexRowToModelInvariantIndexInternal( modelIndexRow, false ); + return d->modelIndexRowToModelInvariantIndexInternal( modelIndexRow, false ); } QList< ModelInvariantIndex * > * ModelInvariantRowMapper::modelIndexRowRangeToModelInvariantIndexList( int startIndexRow, int count ) { - if ( !d->mRowShiftList ) - { - if ( d->mCurrentInvariantHash->isEmpty() ) - return 0; // no invariants emitted, even if rows are changed, no invariant is affected. - } + if ( !d->mRowShiftList ) + { + if ( d->mCurrentInvariantHash->isEmpty() ) + return 0; // no invariants emitted, even if rows are changed, no invariant is affected. + } - // Find the invariants in range. - // It's somewhat impossible to split this in chunks. + // Find the invariants in range. + // It's somewhat impossible to split this in chunks. - QList< ModelInvariantIndex * > * invariantList = new QList< ModelInvariantIndex * >(); + QList< ModelInvariantIndex * > * invariantList = new QList< ModelInvariantIndex * >(); - const int end = startIndexRow + count; - for ( int idx = startIndexRow; idx < end; idx++ ) - { - ModelInvariantIndex * invariant = d->modelIndexRowToModelInvariantIndexInternal( idx, true ); - if ( invariant ) - invariantList->append( invariant ); - } + const int end = startIndexRow + count; + for ( int idx = startIndexRow; idx < end; idx++ ) + { + ModelInvariantIndex * invariant = d->modelIndexRowToModelInvariantIndexInternal( idx, true ); + if ( invariant ) + invariantList->append( invariant ); + } - if ( invariantList->isEmpty() ) - { - delete invariantList; - return 0; - } + if ( invariantList->isEmpty() ) + { + delete invariantList; + return 0; + } - return invariantList; + return invariantList; } void ModelInvariantRowMapper::modelRowsInserted( int modelIndexRowPosition, int count ) { - // Some rows were added to the model at modelIndexRowPosition. + // Some rows were added to the model at modelIndexRowPosition. - // FIXME: If rows are added at the end then we don't need any mapping. - // The fact is that we don't know which is the model's end... - // But maybe we can consider the end being the greatest row - // index emitted until now... + // FIXME: If rows are added at the end then we don't need any mapping. + // The fact is that we don't know which is the model's end... + // But maybe we can consider the end being the greatest row + // index emitted until now... - if ( !d->mRowShiftList ) - { - if ( d->mCurrentInvariantHash->isEmpty() ) - return; // no invariants emitted, even if rows are changed, no invariant is affected. - // some invariants might be affected - d->mRowShiftList = new QList< RowShift * >(); - } + if ( !d->mRowShiftList ) + { + if ( d->mCurrentInvariantHash->isEmpty() ) + return; // no invariants emitted, even if rows are changed, no invariant is affected. + // some invariants might be affected + d->mRowShiftList = new QList< RowShift * >(); + } - RowShift * shift; + RowShift * shift; - if ( d->mCurrentInvariantHash->isEmpty() ) - { - // No invariants updated (all existing are outdated) + if ( d->mCurrentInvariantHash->isEmpty() ) + { + // No invariants updated (all existing are outdated) - Q_ASSERT( d->mRowShiftList->count() > 0 ); // must be true since it's not null + Q_ASSERT( d->mRowShiftList->count() > 0 ); // must be true since it's not null - // Check if we can attach to the last existing shift (very common for consecutive row additions) - shift = d->mRowShiftList->at( d->mRowShiftList->count() - 1 ); - Q_ASSERT( shift ); + // Check if we can attach to the last existing shift (very common for consecutive row additions) + shift = d->mRowShiftList->at( d->mRowShiftList->count() - 1 ); + Q_ASSERT( shift ); - if ( shift->mShift > 0 ) // the shift was positive (addition) - { - if ( ( shift->mMinimumRowIndex + shift->mShift ) == modelIndexRowPosition ) - { - // Inserting contiguous blocks of rows, just extend this shift - shift->mShift += count; - Q_ASSERT( d->mUpdateTimer->isActive() ); - return; - } + if ( shift->mShift > 0 ) // the shift was positive (addition) + { + if ( ( shift->mMinimumRowIndex + shift->mShift ) == modelIndexRowPosition ) + { + // Inserting contiguous blocks of rows, just extend this shift + shift->mShift += count; + Q_ASSERT( d->mUpdateTimer->isActive() ); + return; + } + } } - } - // FIXME: If we have few items, we can just shift the indexes now. + // FIXME: If we have few items, we can just shift the indexes now. - shift = new RowShift( modelIndexRowPosition, count, d->mCurrentInvariantHash ); - d->mRowShiftList->append( shift ); + shift = new RowShift( modelIndexRowPosition, count, d->mCurrentInvariantHash ); + d->mRowShiftList->append( shift ); - d->mCurrentShiftSerial++; - d->mCurrentInvariantHash = new QHash< int, ModelInvariantIndex * >(); + d->mCurrentShiftSerial++; + d->mCurrentInvariantHash = new QHash< int, ModelInvariantIndex * >(); - if ( d->mRowShiftList->count() > 7 ) // 7 is heuristic - { - // We start loosing performance as the stack is growing too much. - // Start updating NOW and hope we can get it in few sweeps. + if ( d->mRowShiftList->count() > 7 ) // 7 is heuristic + { + // We start loosing performance as the stack is growing too much. + // Start updating NOW and hope we can get it in few sweeps. - if ( d->mUpdateTimer->isActive() ) - d->mUpdateTimer->stop(); + if ( d->mUpdateTimer->isActive() ) + d->mUpdateTimer->stop(); - d->slotPerformLazyUpdate(); + d->slotPerformLazyUpdate(); - } else { - // Make sure we'll get a lazy update somewhere in the future - if ( !d->mUpdateTimer->isActive() ) - d->mUpdateTimer->start( d->mLazyUpdateIdleInterval ); - } + } else { + // Make sure we'll get a lazy update somewhere in the future + if ( !d->mUpdateTimer->isActive() ) + d->mUpdateTimer->start( d->mLazyUpdateIdleInterval ); + } } QList< ModelInvariantIndex * > * ModelInvariantRowMapper::modelRowsRemoved( int modelIndexRowPosition, int count ) { - // Some rows were added from the model at modelIndexRowPosition. + // Some rows were added from the model at modelIndexRowPosition. - // FIXME: If rows are removed from the end, we don't need any mapping. - // The fact is that we don't know which is the model's end... - // But maybe we can consider the end being the greatest row - // index emitted until now... + // FIXME: If rows are removed from the end, we don't need any mapping. + // The fact is that we don't know which is the model's end... + // But maybe we can consider the end being the greatest row + // index emitted until now... - if ( !d->mRowShiftList ) - { - if ( d->mCurrentInvariantHash->isEmpty() ) - return 0; // no invariants emitted, even if rows are changed, no invariant is affected. - // some invariants might be affected - } - - // FIXME: If we have few items, we can just shift the indexes now. - - // FIXME: Find a way to "merge" the shifts, if possible - // It OFTEN happens that we remove a lot of items at once (as opposed - // to item addition which is usually an incremental operation). - - // FIXME: HUGE PROBLEM - // When the items arent contiguous or are just out of order it's - // impossible to merge the shifts. Deleting many messages - // generates then a very deep delta stack. Since to delete the - // next message you need to traverse the whole stack, this method - // becomes very slow (maybe not as slow as updating all the indexes - // in the general case, but still *slow*). - // - // So one needs to perform updates while rows are being removed - // but that tends to void all your efforts to not update the - // whole list of items every time... - // - // Also deletions don't seem to be asynchronous (or at least - // they eat all the CPU power available for KMail) so the timers - // don't fire and we're not actually processing the model jobs... - // - // It turns out that deleting many items is just slower than - // reloading the view... - - // Invalidate the invariants affected by the change - // In most cases it's a relatively small sweep (and it's done once). - // It's somewhat impossible to split this in chunks. - - QList< ModelInvariantIndex * > * deadInvariants = new QList< ModelInvariantIndex * >(); - - const int end = modelIndexRowPosition + count; - for ( int idx = modelIndexRowPosition; idx < end; idx++ ) - { - // FIXME: One could optimize this by joining the retrieval and destruction functions - // that is by making a special indexDead( int modelIndex ).. - ModelInvariantIndex * dyingInvariant = d->modelIndexRowToModelInvariantIndexInternal( idx, false ); - if ( dyingInvariant ) - { - d->indexDead( dyingInvariant ); // will remove from this mapper hashes - dyingInvariant->d->setRowMapper( 0 ); // invalidate! - deadInvariants->append( dyingInvariant ); - } else { - // got no dying invariant - kWarning() << "Could not find invariant to invalidate at current row " << idx; + if ( !d->mRowShiftList ) + { + if ( d->mCurrentInvariantHash->isEmpty() ) + return 0; // no invariants emitted, even if rows are changed, no invariant is affected. + // some invariants might be affected } - } - if ( !d->mRowShiftList ) - { - // have no pending shifts, look if we are keeping other invariants - if ( d->mCurrentInvariantHash->isEmpty() ) + // FIXME: If we have few items, we can just shift the indexes now. + + // FIXME: Find a way to "merge" the shifts, if possible + // It OFTEN happens that we remove a lot of items at once (as opposed + // to item addition which is usually an incremental operation). + + // FIXME: HUGE PROBLEM + // When the items arent contiguous or are just out of order it's + // impossible to merge the shifts. Deleting many messages + // generates then a very deep delta stack. Since to delete the + // next message you need to traverse the whole stack, this method + // becomes very slow (maybe not as slow as updating all the indexes + // in the general case, but still *slow*). + // + // So one needs to perform updates while rows are being removed + // but that tends to void all your efforts to not update the + // whole list of items every time... + // + // Also deletions don't seem to be asynchronous (or at least + // they eat all the CPU power available for KMail) so the timers + // don't fire and we're not actually processing the model jobs... + // + // It turns out that deleting many items is just slower than + // reloading the view... + + // Invalidate the invariants affected by the change + // In most cases it's a relatively small sweep (and it's done once). + // It's somewhat impossible to split this in chunks. + + QList< ModelInvariantIndex * > * deadInvariants = new QList< ModelInvariantIndex * >(); + + const int end = modelIndexRowPosition + count; + for ( int idx = modelIndexRowPosition; idx < end; idx++ ) { - // no more invariants in this mapper, even if rows are changed, no invariant is affected. - if ( deadInvariants->isEmpty() ) - { - // should never happen, but well... - delete deadInvariants; - return 0; - } - return deadInvariants; + // FIXME: One could optimize this by joining the retrieval and destruction functions + // that is by making a special indexDead( int modelIndex ).. + ModelInvariantIndex * dyingInvariant = d->modelIndexRowToModelInvariantIndexInternal( idx, false ); + if ( dyingInvariant ) + { + d->indexDead( dyingInvariant ); // will remove from this mapper hashes + dyingInvariant->d->setRowMapper( 0 ); // invalidate! + deadInvariants->append( dyingInvariant ); + } else { + // got no dying invariant + kWarning() << "Could not find invariant to invalidate at current row " << idx; + } } - // still have some invariants inside, must add a shift for them - d->mRowShiftList = new QList< RowShift * >(); - } // else already have shifts - // add a shift for this row removal - RowShift * shift = new RowShift( modelIndexRowPosition + count, -count, d->mCurrentInvariantHash ); - d->mRowShiftList->append( shift ); + if ( !d->mRowShiftList ) + { + // have no pending shifts, look if we are keeping other invariants + if ( d->mCurrentInvariantHash->isEmpty() ) + { + // no more invariants in this mapper, even if rows are changed, no invariant is affected. + if ( deadInvariants->isEmpty() ) + { + // should never happen, but well... + delete deadInvariants; + return 0; + } + return deadInvariants; + } + // still have some invariants inside, must add a shift for them + d->mRowShiftList = new QList< RowShift * >(); + } // else already have shifts + + // add a shift for this row removal + RowShift * shift = new RowShift( modelIndexRowPosition + count, -count, d->mCurrentInvariantHash ); + d->mRowShiftList->append( shift ); - d->mCurrentShiftSerial++; - d->mCurrentInvariantHash = new QHash< int, ModelInvariantIndex * >(); + d->mCurrentShiftSerial++; + d->mCurrentInvariantHash = new QHash< int, ModelInvariantIndex * >(); - // trigger updates - if ( d->mRowShiftList->count() > 7 ) // 7 is heuristic - { - // We start loosing performance as the stack is growing too much. - // Start updating NOW and hope we can get it in few sweeps. + // trigger updates + if ( d->mRowShiftList->count() > 7 ) // 7 is heuristic + { + // We start loosing performance as the stack is growing too much. + // Start updating NOW and hope we can get it in few sweeps. - if ( d->mUpdateTimer->isActive() ) - d->mUpdateTimer->stop(); + if ( d->mUpdateTimer->isActive() ) + d->mUpdateTimer->stop(); - d->slotPerformLazyUpdate(); + d->slotPerformLazyUpdate(); - } else { - // Make sure we'll get a lazy update somewhere in the future - if ( !d->mUpdateTimer->isActive() ) - d->mUpdateTimer->start( d->mLazyUpdateIdleInterval ); - } - - if ( deadInvariants->isEmpty() ) - { - // should never happen, but well... - delete deadInvariants; - return 0; - } + } else { + // Make sure we'll get a lazy update somewhere in the future + if ( !d->mUpdateTimer->isActive() ) + d->mUpdateTimer->start( d->mLazyUpdateIdleInterval ); + } - return deadInvariants; + if ( deadInvariants->isEmpty() ) + { + // should never happen, but well... + delete deadInvariants; + return 0; + } + + return deadInvariants; } void ModelInvariantRowMapper::modelReset() { - // FIXME: optimize this (it probably can be optimized by providing a more complex user interface) - QHash< int, ModelInvariantIndex * >::ConstIterator end( d->mCurrentInvariantHash->constEnd() ); + // FIXME: optimize this (it probably can be optimized by providing a more complex user interface) + QHash< int, ModelInvariantIndex * >::ConstIterator end( d->mCurrentInvariantHash->constEnd() ); - for ( QHash< int, ModelInvariantIndex * >::ConstIterator it = d->mCurrentInvariantHash->constBegin(); it != end; ++it ) - ( *it )->d->setRowMapper( 0 ); - d->mCurrentInvariantHash->clear(); - - if ( d->mRowShiftList ) - { - while ( !d->mRowShiftList->isEmpty() ) - delete d->mRowShiftList->takeFirst(); - - delete d->mRowShiftList; - d->mRowShiftList = 0; - } + for ( QHash< int, ModelInvariantIndex * >::ConstIterator it = d->mCurrentInvariantHash->constBegin(); it != end; ++it ) + ( *it )->d->setRowMapper( 0 ); + d->mCurrentInvariantHash->clear(); + + if ( d->mRowShiftList ) + { + while ( !d->mRowShiftList->isEmpty() ) + delete d->mRowShiftList->takeFirst(); - d->mCurrentShiftSerial = 0; - d->mRemovedShiftCount = 0; + delete d->mRowShiftList; + d->mRowShiftList = 0; + } + + d->mCurrentShiftSerial = 0; + d->mRemovedShiftCount = 0; } void ModelInvariantRowMapperPrivate::slotPerformLazyUpdate() { - // The drawback here is that when one row is removed from the middle (say position 500 of 1000) - // then we require ALL the items to be updated...but: - // - // - We can do it very lazily in the background - // - Optimizing this would mean to ALSO keep the indexes in lists or in a large array - // - The list approach would require to keep the indexes sorted - // so it would cost at least N log (N) / 2.. which is worse than N. - // - We could keep a single (or multiple) array as large as the model - // but then we'd have a large memory consumption and large overhead - // when inserting / removing items from the middle. - // - // So finally I think that the multiple hash approach is a "minimum loss" approach. - - QTime startTime = QTime::currentTime(); - - int curIndex = 0; - - while( mRowShiftList ) - { - // Have at least one row shift - uint count = static_cast< uint >( mRowShiftList->count() ); + // The drawback here is that when one row is removed from the middle (say position 500 of 1000) + // then we require ALL the items to be updated...but: + // + // - We can do it very lazily in the background + // - Optimizing this would mean to ALSO keep the indexes in lists or in a large array + // - The list approach would require to keep the indexes sorted + // so it would cost at least N log (N) / 2.. which is worse than N. + // - We could keep a single (or multiple) array as large as the model + // but then we'd have a large memory consumption and large overhead + // when inserting / removing items from the middle. + // + // So finally I think that the multiple hash approach is a "minimum loss" approach. - // Grab it - RowShift * shift = mRowShiftList->at( 0 ); + QTime startTime = QTime::currentTime(); - // and update the invariants that belong to it - QHash< int, ModelInvariantIndex * >::Iterator it = shift->mInvariantHash->begin(); - QHash< int, ModelInvariantIndex * >::Iterator end = shift->mInvariantHash->end(); + int curIndex = 0; - while ( it != end ) + while( mRowShiftList ) { - ModelInvariantIndex * invariant = *it; + // Have at least one row shift + uint count = static_cast< uint >( mRowShiftList->count() ); + + // Grab it + RowShift * shift = mRowShiftList->at( 0 ); - it = shift->mInvariantHash->erase( it ); + // and update the invariants that belong to it + QHash< int, ModelInvariantIndex * >::Iterator it = shift->mInvariantHash->begin(); + QHash< int, ModelInvariantIndex * >::Iterator end = shift->mInvariantHash->end(); - // apply shifts - int modelIndexRow = invariant->d->modelIndexRow(); + while ( it != end ) + { + ModelInvariantIndex * invariant = *it; - for ( uint idx = 0; idx < count; ++idx ) - { - RowShift * thatShift = mRowShiftList->at( idx ); - if ( modelIndexRow >= thatShift->mMinimumRowIndex ) - modelIndexRow += thatShift->mShift; - } + it = shift->mInvariantHash->erase( it ); - // update and make it belong to the current serial - invariant->d->setModelIndexRowAndRowMapperSerial( modelIndexRow, mCurrentShiftSerial ); + // apply shifts + int modelIndexRow = invariant->d->modelIndexRow(); - mCurrentInvariantHash->insert( modelIndexRow, invariant ); + for ( uint idx = 0; idx < count; ++idx ) + { + RowShift * thatShift = mRowShiftList->at( idx ); + if ( modelIndexRow >= thatShift->mMinimumRowIndex ) + modelIndexRow += thatShift->mShift; + } + + // update and make it belong to the current serial + invariant->d->setModelIndexRowAndRowMapperSerial( modelIndexRow, mCurrentShiftSerial ); + + mCurrentInvariantHash->insert( modelIndexRow, invariant ); + + // once in a while check if we ran out of time + if ( ( curIndex % 15 ) == 0 ) // 15 is heuristic + { + int elapsed = startTime.msecsTo( QTime::currentTime() ); + if ( ( elapsed > mLazyUpdateChunkInterval ) || ( elapsed < 0 ) ) + { + // interrupt + //kDebug() << "Lazy update fixed " << curIndex << " invariants " << endl; + mUpdateTimer->start( mLazyUpdateIdleInterval ); + return; + } + } - // once in a while check if we ran out of time - if ( ( curIndex % 15 ) == 0 ) // 15 is heuristic - { - int elapsed = startTime.msecsTo( QTime::currentTime() ); - if ( ( elapsed > mLazyUpdateChunkInterval ) || ( elapsed < 0 ) ) - { - // interrupt - //kDebug() << "Lazy update fixed " << curIndex << " invariants " << endl; - mUpdateTimer->start( mLazyUpdateIdleInterval ); - return; + curIndex++; } - } - curIndex++; + // no more invariants with serial <= invariantToFill->rowMapperSerial() + killFirstRowShift(); } - // no more invariants with serial <= invariantToFill->rowMapperSerial() - killFirstRowShift(); - } - - //kDebug() << "Lazy update fixed " << curIndex << " invariants " << endl; + //kDebug() << "Lazy update fixed " << curIndex << " invariants " << endl; - // if we're here then no more work needs to be done. + // if we're here then no more work needs to be done. } #include "moc_modelinvariantrowmapper.cpp" diff -Nru kdepim-4.12.97/messagelist/core/modelinvariantrowmapper.h kdepim-4.13.0/messagelist/core/modelinvariantrowmapper.h --- kdepim-4.12.97/messagelist/core/modelinvariantrowmapper.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/modelinvariantrowmapper.h 2014-04-10 07:40:20.000000000 +0000 @@ -92,31 +92,31 @@ */ class MESSAGELIST_EXPORT ModelInvariantRowMapper : public QObject { - friend class ModelInvariantIndex; + friend class ModelInvariantIndex; - Q_OBJECT + Q_OBJECT public: - explicit ModelInvariantRowMapper(); - virtual ~ModelInvariantRowMapper(); + explicit ModelInvariantRowMapper(); + virtual ~ModelInvariantRowMapper(); - /** + /** * Sets the maximum time we can spend inside a single lazy update step. * The larger this time, the more resources we consume and leave less to UI processing * but also larger the update throughput (that is, we update more items per second). * This is 50 msec by default. */ - void setLazyUpdateChunkInterval( int chunkInterval ); + void setLazyUpdateChunkInterval( int chunkInterval ); - /** + /** * Sets the idle time between two lazy updates in milliseconds. * The larger this time, the less resources we consume and leave more to UI processing * but also smaller the update throughput (that is, we update less items per second). * This is 50 msec by default. */ - void setLazyUpdateIdleInterval( int idleInterval ); + void setLazyUpdateIdleInterval( int idleInterval ); - /** + /** * Maps a ModelInvariantIndex to the CURRENT associated row index in the model. * As long as the underlying model is consistent, the returned row index is guaranteed to * point to the content that this ModelInvariantIndex pointed at the time it was created. @@ -124,9 +124,9 @@ * Returns the current associated row index in the model or -1 if the invariant * does not belong to this mapper (model) or is marked as invalid at all. */ - int modelInvariantIndexToModelIndexRow( ModelInvariantIndex * invariant ); + int modelInvariantIndexToModelIndexRow( ModelInvariantIndex * invariant ); - /** + /** * Binds a ModelInvariantIndex structure to the specified CURRENT modelIndexRow. * Later you can use the ModelInvariantIndex to retrieve the model contents * that the parameter modelIndexRow refers to... even if the model changes. @@ -135,32 +135,32 @@ * * This function ASSUMES that invariantToFill is a newly allocated ModelInvariantIndex. */ - void createModelInvariantIndex( int modelIndexRow, ModelInvariantIndex * invariantToFill ); + void createModelInvariantIndex( int modelIndexRow, ModelInvariantIndex * invariantToFill ); - /** + /** * Finds the existing ModelInvariantIndex that belongs to the specified CURRENT modelIndexRow. * Returns the ModelInvariantIndex found or 0 if such an invariant wasn't yet * created (by the means of createModelInvariantIndex()). */ - ModelInvariantIndex * modelIndexRowToModelInvariantIndex( int modelIndexRow ); + ModelInvariantIndex * modelIndexRowToModelInvariantIndex( int modelIndexRow ); - /** + /** * This basically applies modelIndexRowToModelInvariantIndex() to a range of elements. * The returned pointer can be null if no existing ModelInvariantIndex object were * present in the range (this can happen if you don't request some of them). If the returned * value is not 0 then you're responsable of deleting it. */ - QList< ModelInvariantIndex * > * modelIndexRowRangeToModelInvariantIndexList( int startIndexRow, int count ); + QList< ModelInvariantIndex * > * modelIndexRowRangeToModelInvariantIndexList( int startIndexRow, int count ); - /** + /** * Call this function when rows are inserted to the underlying model * BEFORE scanning the model for the new items. You probably * want this function to be the first call in your rowsInserted() handler * or the last call in the rowsAboutToBeInserted() handler. */ - void modelRowsInserted( int modelIndexRowPosition, int count ); + void modelRowsInserted( int modelIndexRowPosition, int count ); - /** + /** * Call this function when rows are removed from the underlying model * AFTER accessing the removed rows for the last time. You probably * want this function to be the first call of your rowsRemoved() handler @@ -174,9 +174,9 @@ * (this can happen if you don't request some of them). If the returned * value is not 0 then you're responsable of deleting it. */ - QList< ModelInvariantIndex * > * modelRowsRemoved( int modelIndexRowPosition, int count ); + QList< ModelInvariantIndex * > * modelRowsRemoved( int modelIndexRowPosition, int count ); - /** + /** * Call this function from your handlers of reset() and layoutChanged() * AFTER you ve last accessed the model underlying data. * You probably want this function to be the first call of your @@ -185,12 +185,12 @@ * This function assumes that all the ModelInvariantIndex * are being invalidated and need to be requeried. */ - void modelReset(); + void modelReset(); private: - Q_PRIVATE_SLOT(d, void slotPerformLazyUpdate()) + Q_PRIVATE_SLOT(d, void slotPerformLazyUpdate()) - ModelInvariantRowMapperPrivate * const d; + ModelInvariantRowMapperPrivate * const d; }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/optionset.cpp kdepim-4.13.0/messagelist/core/optionset.cpp --- kdepim-4.12.97/messagelist/core/optionset.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/optionset.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -34,20 +34,20 @@ using namespace MessageList::Core; OptionSet::OptionSet() - : mReadOnly( false ) + : mReadOnly( false ) { - generateUniqueId(); + generateUniqueId(); } OptionSet::OptionSet( const OptionSet &set ) - : mId( set.mId ), mName( set.mName ), mDescription( set.mDescription ), mReadOnly( set.mReadOnly ) + : mId( set.mId ), mName( set.mName ), mDescription( set.mDescription ), mReadOnly( set.mReadOnly ) { } OptionSet::OptionSet( const QString &name, const QString &description, bool readOnly ) - : mName( name ), mDescription( description ), mReadOnly( readOnly ) + : mName( name ), mDescription( description ), mReadOnly( readOnly ) { - generateUniqueId(); + generateUniqueId(); } OptionSet::~OptionSet() @@ -56,78 +56,78 @@ void OptionSet::generateUniqueId() { - static int nextUniqueId = 0; - nextUniqueId++; - mId = QString::fromLatin1( "%1-%2" ).arg( (unsigned int)::time(0) ).arg( nextUniqueId ); + static int nextUniqueId = 0; + nextUniqueId++; + mId = QString::fromLatin1( "%1-%2" ).arg( (unsigned int)::time(0) ).arg( nextUniqueId ); } QString OptionSet::saveToString() const { - QByteArray raw; + QByteArray raw; - { - QDataStream s( &raw, QIODevice::WriteOnly ); + { + QDataStream s( &raw, QIODevice::WriteOnly ); - s << gOptionSetInitialMarker; - s << gOptionSetWithReadOnLyModeVersion; - s << mId; - s << mName; - s << mDescription; - s << mReadOnly; + s << gOptionSetInitialMarker; + s << gOptionSetWithReadOnLyModeVersion; + s << mId; + s << mName; + s << mDescription; + s << mReadOnly; - save( s ); + save( s ); - s << gOptionSetFinalMarker; - } + s << gOptionSetFinalMarker; + } - return QString::fromLatin1( raw.toHex() ); + return QString::fromLatin1( raw.toHex() ); } bool OptionSet::loadFromString(const QString &data ) { - QByteArray raw = QByteArray::fromHex( data.toLatin1() ); + QByteArray raw = QByteArray::fromHex( data.toLatin1() ); - QDataStream s( &raw, QIODevice::ReadOnly ); + QDataStream s( &raw, QIODevice::ReadOnly ); - int marker; + int marker; - s >> marker; + s >> marker; - if ( marker != gOptionSetInitialMarker ) - return false; // invalid configuration + if ( marker != gOptionSetInitialMarker ) + return false; // invalid configuration - int currentVersion; + int currentVersion; - s >> currentVersion; + s >> currentVersion; - if ( currentVersion > gOptionSetWithReadOnLyModeVersion) - return false; // invalid configuration + if ( currentVersion > gOptionSetWithReadOnLyModeVersion) + return false; // invalid configuration - s >> mId; + s >> mId; - if ( mId.isEmpty() ) - return false; // invalid configuration + if ( mId.isEmpty() ) + return false; // invalid configuration - s >> mName; + s >> mName; - if ( mName.isEmpty() ) - return false; // invalid configuration + if ( mName.isEmpty() ) + return false; // invalid configuration - s >> mDescription; + s >> mDescription; - bool readOnly = false; - if ( currentVersion == gOptionSetWithReadOnLyModeVersion ) - s >> readOnly; - mReadOnly = readOnly; + bool readOnly = false; + if ( currentVersion == gOptionSetWithReadOnLyModeVersion ) + s >> readOnly; + mReadOnly = readOnly; - if ( !load( s ) ) - return false; // invalid configuration + if ( !load( s ) ) + return false; // invalid configuration - s >> marker; + s >> marker; - if ( marker != gOptionSetFinalMarker ) - return false; // invalid configuration + if ( marker != gOptionSetFinalMarker ) + return false; // invalid configuration - return true; + return true; } diff -Nru kdepim-4.12.97/messagelist/core/optionset.h kdepim-4.13.0/messagelist/core/optionset.h --- kdepim-4.12.97/messagelist/core/optionset.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/optionset.h 2014-04-10 07:40:20.000000000 +0000 @@ -47,90 +47,90 @@ class OptionSet { public: - explicit OptionSet(); - explicit OptionSet( const OptionSet &src ); - explicit OptionSet( const QString &name, const QString &description, bool readOnly = false ); - virtual ~OptionSet(); + explicit OptionSet(); + explicit OptionSet( const OptionSet &src ); + explicit OptionSet( const QString &name, const QString &description, bool readOnly = false ); + virtual ~OptionSet(); protected: - QString mId; - QString mName; - QString mDescription; - bool mReadOnly; + QString mId; + QString mName; + QString mDescription; + bool mReadOnly; public: - /** + /** * Returns the unique id of this OptionSet. * The id can't be set. It's either automatically generated or loaded from configuration. */ - const QString &id() const + const QString &id() const { return mId; } - /** + /** * Returns the name of this OptionSet */ - const QString &name() const + const QString &name() const { return mName; } - /** + /** * Sets the name of this OptionSet. You must take care * of specifying an _unique_ name in order for the Manager to * store the sets properly. */ - void setName( const QString &name ) + void setName( const QString &name ) { mName = name; } - /** + /** * Returns a description of this option set. Ideally it should contain * its purpose and what to expect from it. But in the end we'll show * whatever the user will put in here. */ - const QString &description() const + const QString &description() const { return mDescription; } - /** + /** * Sets the description for this option set. */ - void setDescription( const QString &description ) + void setDescription( const QString &description ) { mDescription = description; } - /** + /** * Packs this configuration object into a string suitable for storing * in a config file. */ - QString saveToString() const; + QString saveToString() const; - /** + /** * Attempts to unpack this configuration object from a string (that is * likely to come out from a config file). Returns true if the string * was in a valid format and the load operation succeeded, false otherwise. */ - bool loadFromString( const QString &data ); + bool loadFromString( const QString &data ); - /** + /** * (Re)generates a (hopefully) unique identifier for this option set. * Please note that this function is reserved to this class and to * Configure*Dialog instances which need it for cloning option sets. * You shouldn't need to call it. */ - void generateUniqueId(); - - bool readOnly() const { return mReadOnly; } - void setReadOnly( bool b) { mReadOnly = b; } + void generateUniqueId(); + + bool readOnly() const { return mReadOnly; } + void setReadOnly( bool b) { mReadOnly = b; } protected: - /** + /** * Saves the inner contents of this option set to the specified data stream. * The implementation of this method MUST be provided by derived classes. */ - virtual void save( QDataStream &s ) const = 0; + virtual void save( QDataStream &s ) const = 0; - /** + /** * Loads the inner contents of this option set from the specified data stream. * The implementation of this method MUST be provided by derived classes * and must return true in case of success and false in case of load failure. */ - virtual bool load( QDataStream &s ) = 0; + virtual bool load( QDataStream &s ) = 0; }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/quicksearchline.cpp kdepim-4.13.0/messagelist/core/quicksearchline.cpp --- kdepim-4.12.97/messagelist/core/quicksearchline.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/quicksearchline.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -36,12 +36,14 @@ #include #include #include +#include using namespace MessageList::Core; QuickSearchLine::QuickSearchLine(QWidget *parent) : QWidget(parent), - mContainsOutboundMessages(false) + mContainsOutboundMessages(false), + mFilterStatusMapper(0) { QVBoxLayout *vbox = new QVBoxLayout; vbox->setMargin(0); @@ -58,6 +60,7 @@ mLockSearch = new QToolButton( this ); mLockSearch->setCheckable( true ); mLockSearch->setText( i18nc( "@action:button", "Lock search" ) ); + mLockSearch->setFocusPolicy(Qt::StrongFocus); mLockSearch->setWhatsThis( i18nc( "@info:whatsthis", "Toggle this button if you want to keep your quick search " @@ -106,6 +109,7 @@ mTagFilterCombo->hide(); hbox->addWidget( mTagFilterCombo ); + //Be disable until we have a storageModel => logical that it's disable. mSearchEdit->setEnabled( false ); mTagFilterCombo->setEnabled( false ); @@ -125,18 +129,22 @@ mSearchEveryWhere->setObjectName(QLatin1String("full_message")); mSearchEveryWhere->setFlat(true); mSearchEveryWhere->setCheckable(true); + mSearchEveryWhere->setChecked(true); + connect( mSearchEveryWhere, SIGNAL(clicked()), this, SLOT(slotSearchBy()) ); hbox->addWidget(mSearchEveryWhere); mSearchAgainstBody = new QPushButton(i18n("Body")); mSearchAgainstBody->setObjectName(QLatin1String("body")); mSearchAgainstBody->setFlat(true); mSearchAgainstBody->setCheckable(true); + connect( mSearchAgainstBody, SIGNAL(clicked()), this, SLOT(slotSearchBy()) ); hbox->addWidget(mSearchAgainstBody); mSearchAgainstSubject = new QPushButton(i18n("Subject")); mSearchAgainstSubject->setCheckable(true); mSearchAgainstSubject->setFlat(true); mSearchAgainstSubject->setObjectName(QLatin1String("subject")); + connect( mSearchAgainstSubject, SIGNAL(clicked()), this, SLOT(slotSearchBy()) ); hbox->addWidget(mSearchAgainstSubject); mSearchAgainstFromOrTo = new QPushButton; @@ -144,23 +152,16 @@ mSearchAgainstFromOrTo->setObjectName(QLatin1String("fromorto")); mSearchAgainstFromOrTo->setCheckable(true); mSearchAgainstFromOrTo->setFlat(true); + connect( mSearchAgainstFromOrTo, SIGNAL(clicked()), this, SLOT(slotSearchBy()) ); hbox->addWidget(mSearchAgainstFromOrTo); mSearchAgainstBcc = new QPushButton(i18n("Bcc")); mSearchAgainstBcc->setObjectName(QLatin1String("bcc")); mSearchAgainstBcc->setCheckable(true); mSearchAgainstBcc->setFlat(true); + connect( mSearchAgainstBcc, SIGNAL(clicked()), this, SLOT(slotSearchBy()) ); hbox->addWidget(mSearchAgainstBcc); - mButtonSearchAgainstGroup = new QButtonGroup(this); - mButtonSearchAgainstGroup->addButton(mSearchEveryWhere, 0); - mButtonSearchAgainstGroup->addButton(mSearchAgainstBody); - mButtonSearchAgainstGroup->addButton(mSearchAgainstSubject); - mButtonSearchAgainstGroup->addButton(mSearchAgainstFromOrTo); - mButtonSearchAgainstGroup->addButton(mSearchAgainstBcc); - mButtonSearchAgainstGroup->button(0)->setChecked(true); - connect(mButtonSearchAgainstGroup, SIGNAL(buttonClicked(int)), this, SLOT(slotSearchOptionChanged())); - mButtonSearchAgainstGroup->setExclusive(true); mQuickSearchFilterWidget->hide(); installEventFilter(this); @@ -181,6 +182,28 @@ } +void QuickSearchLine::slotSearchBy() +{ + QObject *button = sender(); + if (mSearchEveryWhere != button) { + mSearchEveryWhere->setChecked(false); + } + if (mSearchAgainstBody != button) { + mSearchAgainstBody->setChecked(false); + } + if (mSearchAgainstSubject != button) { + mSearchAgainstSubject->setChecked(false); + } + if (mSearchAgainstFromOrTo != button) { + mSearchAgainstFromOrTo->setChecked(false); + } + if (mSearchAgainstBcc != button) { + mSearchAgainstBcc->setChecked(false); + } + + slotSearchOptionChanged(); +} + void QuickSearchLine::slotMoreOptionClicked(bool b) { mQuickSearchFilterWidget->setVisible(b); @@ -208,7 +231,7 @@ void QuickSearchLine::slotClearButtonClicked() { mExtraOption->hide(); - mButtonSearchAgainstGroup->button(0)->setChecked(true); + mSearchEveryWhere->setChecked(true); if (mTagFilterCombo->isVisible()) mTagFilterCombo->setCurrentIndex(0); Q_EMIT clearButtonClicked(); @@ -283,7 +306,7 @@ if (mTagFilterCombo->isVisible()) mTagFilterCombo->setCurrentIndex( 0 ); mLockSearch->setChecked(false); - mButtonSearchAgainstGroup->button(0)->setChecked(true); + mSearchEveryWhere->setChecked(true); mExtraOption->hide(); } @@ -297,11 +320,12 @@ button->setCheckable(true); button->setChecked(false); button->setProperty("statusvalue", value); + mFilterStatusMapper->setMapping(button, value); + connect( button, SIGNAL(clicked(bool)), mFilterStatusMapper, SLOT(map()) ); quickSearchButtonLayout->addWidget(button); button->installEventFilter(this); button->setFocusPolicy(Qt::StrongFocus); mListStatusButton.append(button); - mButtonStatusGroup->addButton(button); } bool QuickSearchLine::containsOutboundMessages() const @@ -328,9 +352,9 @@ void QuickSearchLine::initializeStatusSearchButton(QLayout *quickSearchButtonLayout) { - mButtonStatusGroup = new QButtonGroup(this); - mButtonStatusGroup->setExclusive(false); - connect(mButtonStatusGroup, SIGNAL(buttonClicked(int)), this, SIGNAL(statusButtonsClicked())); + //Bug Qt we can't use QButtonGroup + QToolButton + change focus. => use QSignalMapper(); + mFilterStatusMapper = new QSignalMapper(this); + connect(mFilterStatusMapper, SIGNAL(mapped(int)), this, SIGNAL(statusButtonsClicked())); createQuickSearchButton(SmallIcon(QLatin1String( "mail-unread" )), i18nc( "@action:inmenu Status of a message", "Unread" ), Akonadi::MessageStatus::statusUnread().toQInt32(),quickSearchButtonLayout ); @@ -397,7 +421,7 @@ bool QuickSearchLine::eventFilter(QObject *object, QEvent *e) { const bool shortCutOverride = (e->type() == QEvent::ShortcutOverride); - if (shortCutOverride || e->type() == QEvent::KeyPress ) { + if (shortCutOverride) { e->accept(); return true; } diff -Nru kdepim-4.12.97/messagelist/core/quicksearchline.h kdepim-4.13.0/messagelist/core/quicksearchline.h --- kdepim-4.12.97/messagelist/core/quicksearchline.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/quicksearchline.h 2014-04-10 07:40:20.000000000 +0000 @@ -29,7 +29,7 @@ class KComboBox; class QToolButton; class QPushButton; -class QButtonGroup; +class QSignalMapper; class KPushButton; namespace MessageList { namespace Core { @@ -81,7 +81,8 @@ void slotSearchOptionChanged(); void slotSearchEditTextEdited(const QString &text); void slotClearButtonClicked(); - void slotMoreOptionClicked(bool b); + void slotMoreOptionClicked(bool b); + void slotSearchBy(); private: void initializeStatusSearchButton(QLayout *quickSearchButtonLayout); @@ -99,9 +100,8 @@ QPushButton *mSearchAgainstBcc; QWidget *mExtraOption; QWidget *mQuickSearchFilterWidget; - QButtonGroup *mButtonStatusGroup; - QButtonGroup *mButtonSearchAgainstGroup; bool mContainsOutboundMessages; + QSignalMapper *mFilterStatusMapper; }; } } diff -Nru kdepim-4.12.97/messagelist/core/sortorder.cpp kdepim-4.13.0/messagelist/core/sortorder.cpp --- kdepim-4.12.97/messagelist/core/sortorder.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/sortorder.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -28,91 +28,91 @@ using namespace MessageList::Core; SortOrder::SortOrder() - : mMessageSorting( SortMessagesByDateTime ), - mMessageSortDirection( Descending ), - mGroupSorting( NoGroupSorting ), - mGroupSortDirection( Ascending ) + : mMessageSorting( SortMessagesByDateTime ), + mMessageSortDirection( Descending ), + mGroupSorting( NoGroupSorting ), + mGroupSortDirection( Ascending ) { } QList< QPair< QString, int > > SortOrder::enumerateMessageSortingOptions( Aggregation::Threading t ) { - QList< QPair< QString, int > > ret; - ret.append( QPair< QString, int >( i18n( "None (Storage Order)" ), SortOrder::NoMessageSorting ) ); - ret.append( QPair< QString, int >( i18n( "By Date/Time" ), SortOrder::SortMessagesByDateTime ) ); - if ( t != Aggregation::NoThreading ) - ret.append( QPair< QString, int >( i18n( "By Date/Time of Most Recent in Subtree" ), SortOrder::SortMessagesByDateTimeOfMostRecent ) ); - ret.append( QPair< QString, int >( i18n( "By Sender" ), SortOrder::SortMessagesBySender ) ); - ret.append( QPair< QString, int >( i18n( "By Receiver" ), SortOrder::SortMessagesByReceiver ) ); - ret.append( QPair< QString, int >( i18n( "By Smart Sender/Receiver" ), SortOrder::SortMessagesBySenderOrReceiver ) ); - ret.append( QPair< QString, int >( i18n( "By Subject" ), SortOrder::SortMessagesBySubject ) ); - ret.append( QPair< QString, int >( i18n( "By Size" ), SortOrder::SortMessagesBySize ) ); - ret.append( QPair< QString, int >( i18n( "By Action Item Status" ), SortOrder::SortMessagesByActionItemStatus ) ); - ret.append( QPair< QString, int >( i18n( "By Unread Status" ), SortOrder::SortMessagesByUnreadStatus ) ); - ret.append( QPair< QString, int >( i18n( "By Important Status" ), SortOrder::SortMessagesByImportantStatus ) ); - return ret; + QList< QPair< QString, int > > ret; + ret.append( QPair< QString, int >( i18n( "None (Storage Order)" ), SortOrder::NoMessageSorting ) ); + ret.append( QPair< QString, int >( i18n( "By Date/Time" ), SortOrder::SortMessagesByDateTime ) ); + if ( t != Aggregation::NoThreading ) + ret.append( QPair< QString, int >( i18n( "By Date/Time of Most Recent in Subtree" ), SortOrder::SortMessagesByDateTimeOfMostRecent ) ); + ret.append( QPair< QString, int >( i18n( "By Sender" ), SortOrder::SortMessagesBySender ) ); + ret.append( QPair< QString, int >( i18n( "By Receiver" ), SortOrder::SortMessagesByReceiver ) ); + ret.append( QPair< QString, int >( i18n( "By Smart Sender/Receiver" ), SortOrder::SortMessagesBySenderOrReceiver ) ); + ret.append( QPair< QString, int >( i18n( "By Subject" ), SortOrder::SortMessagesBySubject ) ); + ret.append( QPair< QString, int >( i18n( "By Size" ), SortOrder::SortMessagesBySize ) ); + ret.append( QPair< QString, int >( i18n( "By Action Item Status" ), SortOrder::SortMessagesByActionItemStatus ) ); + ret.append( QPair< QString, int >( i18n( "By Unread Status" ), SortOrder::SortMessagesByUnreadStatus ) ); + ret.append( QPair< QString, int >( i18n( "By Important Status" ), SortOrder::SortMessagesByImportantStatus ) ); + return ret; } QList< QPair< QString, int > > SortOrder::enumerateMessageSortDirectionOptions( MessageSorting ms ) { - QList< QPair< QString, int > > ret; - if ( ms == SortOrder::NoMessageSorting ) - return ret; + QList< QPair< QString, int > > ret; + if ( ms == SortOrder::NoMessageSorting ) + return ret; + + if ( + ( ms == SortOrder::SortMessagesByDateTime ) || + ( ms == SortOrder::SortMessagesByDateTimeOfMostRecent ) + ) + { + ret.append( QPair< QString, int >( i18n( "Least Recent on Top" ), SortOrder::Ascending ) ); + ret.append( QPair< QString, int >( i18n( "Most Recent on Top" ), SortOrder::Descending ) ); + return ret; + } - if ( - ( ms == SortOrder::SortMessagesByDateTime ) || - ( ms == SortOrder::SortMessagesByDateTimeOfMostRecent ) - ) - { - ret.append( QPair< QString, int >( i18n( "Least Recent on Top" ), SortOrder::Ascending ) ); - ret.append( QPair< QString, int >( i18n( "Most Recent on Top" ), SortOrder::Descending ) ); + ret.append( QPair< QString, int >( i18nc( "Sort order for messages", "Ascending" ), SortOrder::Ascending ) ); + ret.append( QPair< QString, int >( i18nc( "Sort order for messages", "Descending" ), SortOrder::Descending ) ); return ret; - } - - ret.append( QPair< QString, int >( i18nc( "Sort order for messages", "Ascending" ), SortOrder::Ascending ) ); - ret.append( QPair< QString, int >( i18nc( "Sort order for messages", "Descending" ), SortOrder::Descending ) ); - return ret; } QList< QPair< QString, int > > SortOrder::enumerateGroupSortingOptions( Aggregation::Grouping g ) { - QList< QPair< QString, int > > ret; - if ( g == Aggregation::NoGrouping ) - return ret; - if ( ( g == Aggregation::GroupByDate ) || ( g == Aggregation::GroupByDateRange ) ) - ret.append( QPair< QString, int >( i18n( "by Date/Time" ), SortOrder::SortGroupsByDateTime ) ); - else { - ret.append( QPair< QString, int >( i18n( "None (Storage Order)" ), SortOrder::NoGroupSorting ) ); - ret.append( QPair< QString, int >( i18n( "by Date/Time of Most Recent Message in Group" ), SortOrder::SortGroupsByDateTimeOfMostRecent ) ); - } - - if ( g == Aggregation::GroupBySenderOrReceiver ) - ret.append( QPair< QString, int >( i18n( "by Sender/Receiver" ), SortOrder::SortGroupsBySenderOrReceiver ) ); - else if ( g == Aggregation::GroupBySender ) - ret.append( QPair< QString, int >( i18n( "by Sender" ), SortOrder::SortGroupsBySender ) ); - else if ( g == Aggregation::GroupByReceiver ) - ret.append( QPair< QString, int >( i18n( "by Receiver" ), SortOrder::SortGroupsByReceiver ) ); + QList< QPair< QString, int > > ret; + if ( g == Aggregation::NoGrouping ) + return ret; + if ( ( g == Aggregation::GroupByDate ) || ( g == Aggregation::GroupByDateRange ) ) + ret.append( QPair< QString, int >( i18n( "by Date/Time" ), SortOrder::SortGroupsByDateTime ) ); + else { + ret.append( QPair< QString, int >( i18n( "None (Storage Order)" ), SortOrder::NoGroupSorting ) ); + ret.append( QPair< QString, int >( i18n( "by Date/Time of Most Recent Message in Group" ), SortOrder::SortGroupsByDateTimeOfMostRecent ) ); + } + + if ( g == Aggregation::GroupBySenderOrReceiver ) + ret.append( QPair< QString, int >( i18n( "by Sender/Receiver" ), SortOrder::SortGroupsBySenderOrReceiver ) ); + else if ( g == Aggregation::GroupBySender ) + ret.append( QPair< QString, int >( i18n( "by Sender" ), SortOrder::SortGroupsBySender ) ); + else if ( g == Aggregation::GroupByReceiver ) + ret.append( QPair< QString, int >( i18n( "by Receiver" ), SortOrder::SortGroupsByReceiver ) ); - return ret; + return ret; } QList< QPair< QString, int > > SortOrder::enumerateGroupSortDirectionOptions( Aggregation::Grouping g, GroupSorting gs ) { - QList< QPair< QString, int > > ret; - if ( g == Aggregation::NoGrouping || gs == SortOrder::NoGroupSorting) - return ret; - - if ( gs == SortOrder::SortGroupsByDateTimeOfMostRecent ) - { - ret.append( QPair< QString, int >( i18n( "Least Recent on Top" ), SortOrder::Ascending ) ); - ret.append( QPair< QString, int >( i18n( "Most Recent on Top" ), SortOrder::Descending ) ); + QList< QPair< QString, int > > ret; + if ( g == Aggregation::NoGrouping || gs == SortOrder::NoGroupSorting) + return ret; + + if ( gs == SortOrder::SortGroupsByDateTimeOfMostRecent ) + { + ret.append( QPair< QString, int >( i18n( "Least Recent on Top" ), SortOrder::Ascending ) ); + ret.append( QPair< QString, int >( i18n( "Most Recent on Top" ), SortOrder::Descending ) ); + return ret; + } + ret.append( QPair< QString, int >( i18nc( "Sort order for mail groups", "Ascending" ), SortOrder::Ascending ) ); + ret.append( QPair< QString, int >( i18nc( "Sort order for mail groups", "Descending" ), SortOrder::Descending ) ); return ret; - } - ret.append( QPair< QString, int >( i18nc( "Sort order for mail groups", "Ascending" ), SortOrder::Ascending ) ); - ret.append( QPair< QString, int >( i18nc( "Sort order for mail groups", "Descending" ), SortOrder::Descending ) ); - return ret; } typedef QPair< QString, int > Pair; @@ -120,153 +120,153 @@ static bool optionListHasOption( const OptionList &optionList, int optionValue, int defaultOptionValue ) { - foreach( const Pair &pair, optionList ) { - if ( pair.second == optionValue ) { - return true; + foreach( const Pair &pair, optionList ) { + if ( pair.second == optionValue ) { + return true; + } } - } - if ( optionValue != defaultOptionValue ) - return false; - else return true; + if ( optionValue != defaultOptionValue ) + return false; + else return true; } bool SortOrder::validForAggregation( const Aggregation *aggregation ) const { - OptionList messageSortings = enumerateMessageSortingOptions( aggregation->threading() ); - OptionList messageSortDirections = enumerateMessageSortDirectionOptions( mMessageSorting ); - OptionList groupSortings = enumerateGroupSortingOptions( aggregation->grouping() ); - OptionList groupSortDirections = enumerateGroupSortDirectionOptions( aggregation->grouping(), - mGroupSorting ); - SortOrder defaultSortOrder = defaultForAggregation( aggregation, SortOrder() ); - bool messageSortingOk = optionListHasOption( messageSortings, - mMessageSorting, defaultSortOrder.messageSorting() ); - bool messageSortDirectionOk = optionListHasOption( messageSortDirections, mMessageSortDirection, - defaultSortOrder.messageSortDirection() ); - - bool groupSortingOk = optionListHasOption( groupSortings, mGroupSorting, - defaultSortOrder.groupSorting() ); - bool groupSortDirectionOk = optionListHasOption( groupSortDirections, mGroupSortDirection, - defaultSortOrder.groupSortDirection() ); - return messageSortingOk && messageSortDirectionOk && - groupSortingOk && groupSortDirectionOk; + OptionList messageSortings = enumerateMessageSortingOptions( aggregation->threading() ); + OptionList messageSortDirections = enumerateMessageSortDirectionOptions( mMessageSorting ); + OptionList groupSortings = enumerateGroupSortingOptions( aggregation->grouping() ); + OptionList groupSortDirections = enumerateGroupSortDirectionOptions( aggregation->grouping(), + mGroupSorting ); + SortOrder defaultSortOrder = defaultForAggregation( aggregation, SortOrder() ); + bool messageSortingOk = optionListHasOption( messageSortings, + mMessageSorting, defaultSortOrder.messageSorting() ); + bool messageSortDirectionOk = optionListHasOption( messageSortDirections, mMessageSortDirection, + defaultSortOrder.messageSortDirection() ); + + bool groupSortingOk = optionListHasOption( groupSortings, mGroupSorting, + defaultSortOrder.groupSorting() ); + bool groupSortDirectionOk = optionListHasOption( groupSortDirections, mGroupSortDirection, + defaultSortOrder.groupSortDirection() ); + return messageSortingOk && messageSortDirectionOk && + groupSortingOk && groupSortDirectionOk; } SortOrder SortOrder::defaultForAggregation( const Aggregation *aggregation, const SortOrder &oldSortOrder ) { - SortOrder newSortOrder; + SortOrder newSortOrder; - // - // First check if we can adopt the message sorting and the message sort direction from - // the old sort order. This is mostly true, except, for example, when the old message sorting - // was "by most recent in subtree", and the aggregation doesn't use threading. - // - OptionList messageSortings = enumerateMessageSortingOptions( aggregation->threading() ); - bool messageSortingOk = optionListHasOption( messageSortings, - oldSortOrder.messageSorting(), - SortOrder().messageSorting() ); - bool messageSortDirectionOk = false; - if ( messageSortingOk ) { - OptionList messageSortDirections = enumerateMessageSortDirectionOptions( - oldSortOrder.messageSorting() ); - messageSortDirectionOk = optionListHasOption( messageSortDirections, oldSortOrder.messageSortDirection(), - SortOrder().messageSortDirection() ); - } - - // - // Ok, if we can partly adopt the old sort order, set the values now. - // - if ( messageSortingOk ) - newSortOrder.setMessageSorting( oldSortOrder.messageSorting() ); - else - newSortOrder.setMessageSorting( SortMessagesByDateTime ); - if ( messageSortDirectionOk ) - newSortOrder.setMessageSortDirection( oldSortOrder.messageSortDirection() ); - else - newSortOrder.setMessageSortDirection( Descending ); - - // - // Now set the group sorting and group sort direction, depending on the aggregation. - // - Aggregation::Grouping grouping = aggregation->grouping(); - if ( grouping == Aggregation::GroupByDate || - grouping == Aggregation::GroupByDateRange ) { - newSortOrder.setGroupSortDirection( Descending ); - newSortOrder.setGroupSorting( SortGroupsByDateTime ); - - } - else if ( grouping == Aggregation::GroupByReceiver || grouping == Aggregation::GroupBySender || - grouping == Aggregation::GroupBySenderOrReceiver ) { - newSortOrder.setGroupSortDirection( Descending ); - switch ( grouping ) { - case Aggregation::GroupByReceiver: - newSortOrder.setGroupSorting( SortGroupsByReceiver ); break; - case Aggregation::GroupBySender: - newSortOrder.setGroupSorting( SortGroupsBySender ); break; - case Aggregation::GroupBySenderOrReceiver: - newSortOrder.setGroupSorting( SortGroupsBySenderOrReceiver ); break; - default: break; + // + // First check if we can adopt the message sorting and the message sort direction from + // the old sort order. This is mostly true, except, for example, when the old message sorting + // was "by most recent in subtree", and the aggregation doesn't use threading. + // + OptionList messageSortings = enumerateMessageSortingOptions( aggregation->threading() ); + bool messageSortingOk = optionListHasOption( messageSortings, + oldSortOrder.messageSorting(), + SortOrder().messageSorting() ); + bool messageSortDirectionOk = false; + if ( messageSortingOk ) { + OptionList messageSortDirections = enumerateMessageSortDirectionOptions( + oldSortOrder.messageSorting() ); + messageSortDirectionOk = optionListHasOption( messageSortDirections, oldSortOrder.messageSortDirection(), + SortOrder().messageSortDirection() ); } - } - return newSortOrder; + // + // Ok, if we can partly adopt the old sort order, set the values now. + // + if ( messageSortingOk ) + newSortOrder.setMessageSorting( oldSortOrder.messageSorting() ); + else + newSortOrder.setMessageSorting( SortMessagesByDateTime ); + if ( messageSortDirectionOk ) + newSortOrder.setMessageSortDirection( oldSortOrder.messageSortDirection() ); + else + newSortOrder.setMessageSortDirection( Descending ); + + // + // Now set the group sorting and group sort direction, depending on the aggregation. + // + Aggregation::Grouping grouping = aggregation->grouping(); + if ( grouping == Aggregation::GroupByDate || + grouping == Aggregation::GroupByDateRange ) { + newSortOrder.setGroupSortDirection( Descending ); + newSortOrder.setGroupSorting( SortGroupsByDateTime ); + + } + else if ( grouping == Aggregation::GroupByReceiver || grouping == Aggregation::GroupBySender || + grouping == Aggregation::GroupBySenderOrReceiver ) { + newSortOrder.setGroupSortDirection( Descending ); + switch ( grouping ) { + case Aggregation::GroupByReceiver: + newSortOrder.setGroupSorting( SortGroupsByReceiver ); break; + case Aggregation::GroupBySender: + newSortOrder.setGroupSorting( SortGroupsBySender ); break; + case Aggregation::GroupBySenderOrReceiver: + newSortOrder.setGroupSorting( SortGroupsBySenderOrReceiver ); break; + default: break; + } + } + + return newSortOrder; } bool SortOrder::readConfigHelper( KConfigGroup &conf, const QString &id ) { - if ( !conf.hasKey( id + MessageList::Util::messageSortingConfigName() ) ) - return false; - mMessageSorting = messageSortingForName( - conf.readEntry( id + MessageList::Util::messageSortingConfigName() ) ); - mMessageSortDirection = sortDirectionForName( - conf.readEntry( id + MessageList::Util::messageSortDirectionConfigName() ) ); - mGroupSorting = groupSortingForName( - conf.readEntry( id + MessageList::Util::groupSortingConfigName() ) ); - mGroupSortDirection = sortDirectionForName( - conf.readEntry( id + MessageList::Util::groupSortDirectionConfigName() ) ); - return true; + if ( !conf.hasKey( id + MessageList::Util::messageSortingConfigName() ) ) + return false; + mMessageSorting = messageSortingForName( + conf.readEntry( id + MessageList::Util::messageSortingConfigName() ) ); + mMessageSortDirection = sortDirectionForName( + conf.readEntry( id + MessageList::Util::messageSortDirectionConfigName() ) ); + mGroupSorting = groupSortingForName( + conf.readEntry( id + MessageList::Util::groupSortingConfigName() ) ); + mGroupSortDirection = sortDirectionForName( + conf.readEntry( id + MessageList::Util::groupSortDirectionConfigName() ) ); + return true; } void SortOrder::readConfig( KConfigGroup &conf, const QString &storageId, bool *storageUsesPrivateSortOrder ) { - SortOrder privateSortOrder, globalSortOrder; - globalSortOrder.readConfigHelper( conf, QLatin1String( "GlobalSortOrder" ) ); - *storageUsesPrivateSortOrder = privateSortOrder.readConfigHelper( conf, storageId ); - if ( *storageUsesPrivateSortOrder ) - *this = privateSortOrder; - else - *this = globalSortOrder; + SortOrder privateSortOrder, globalSortOrder; + globalSortOrder.readConfigHelper( conf, QLatin1String( "GlobalSortOrder" ) ); + *storageUsesPrivateSortOrder = privateSortOrder.readConfigHelper( conf, storageId ); + if ( *storageUsesPrivateSortOrder ) + *this = privateSortOrder; + else + *this = globalSortOrder; } void SortOrder::writeConfig( KConfigGroup &conf, const QString &storageId, bool storageUsesPrivateSortOrder ) const { - QString id = storageId; - if ( !storageUsesPrivateSortOrder ) { - id = QLatin1String( "GlobalSortOrder" ); - conf.deleteEntry( storageId + MessageList::Util::messageSortingConfigName() ); - conf.deleteEntry( storageId + MessageList::Util::messageSortDirectionConfigName() ); - conf.deleteEntry( storageId + MessageList::Util::groupSortingConfigName() ); - conf.deleteEntry( storageId + MessageList::Util::groupSortDirectionConfigName() ); - } - - conf.writeEntry( id + MessageList::Util::messageSortingConfigName(), - nameForMessageSorting( mMessageSorting ) ); - conf.writeEntry( id + MessageList::Util::messageSortDirectionConfigName(), - nameForSortDirection( mMessageSortDirection ) ); - conf.writeEntry( id + MessageList::Util::groupSortingConfigName(), - nameForGroupSorting( mGroupSorting ) ); - conf.writeEntry( id + MessageList::Util::groupSortDirectionConfigName(), - nameForSortDirection( mGroupSortDirection ) ); + QString id = storageId; + if ( !storageUsesPrivateSortOrder ) { + id = QLatin1String( "GlobalSortOrder" ); + conf.deleteEntry( storageId + MessageList::Util::messageSortingConfigName() ); + conf.deleteEntry( storageId + MessageList::Util::messageSortDirectionConfigName() ); + conf.deleteEntry( storageId + MessageList::Util::groupSortingConfigName() ); + conf.deleteEntry( storageId + MessageList::Util::groupSortDirectionConfigName() ); + } + + conf.writeEntry( id + MessageList::Util::messageSortingConfigName(), + nameForMessageSorting( mMessageSorting ) ); + conf.writeEntry( id + MessageList::Util::messageSortDirectionConfigName(), + nameForSortDirection( mMessageSortDirection ) ); + conf.writeEntry( id + MessageList::Util::groupSortingConfigName(), + nameForGroupSorting( mGroupSorting ) ); + conf.writeEntry( id + MessageList::Util::groupSortDirectionConfigName(), + nameForSortDirection( mGroupSortDirection ) ); } bool SortOrder::isValidMessageSorting( SortOrder::MessageSorting ms ) { - switch( ms ) - { + switch( ms ) + { case SortOrder::NoMessageSorting: case SortOrder::SortMessagesByDateTime: case SortOrder::SortMessagesByDateTimeOfMostRecent: @@ -278,54 +278,54 @@ case SortOrder::SortMessagesByActionItemStatus: case SortOrder::SortMessagesByUnreadStatus: case SortOrder::SortMessagesByImportantStatus: - // ok - break; + // ok + break; default: - // b0rken - return false; - break; - } + // b0rken + return false; + break; + } - return true; + return true; } const QString SortOrder::nameForSortDirection( SortDirection sortDirection ) { - int index = staticMetaObject.indexOfEnumerator( "SortDirection" ); - return QLatin1String( staticMetaObject.enumerator( index ).valueToKey( sortDirection ) ); + int index = staticMetaObject.indexOfEnumerator( "SortDirection" ); + return QLatin1String( staticMetaObject.enumerator( index ).valueToKey( sortDirection ) ); } const QString SortOrder::nameForMessageSorting( MessageSorting messageSorting ) { - int index = staticMetaObject.indexOfEnumerator( "MessageSorting" ); - return QLatin1String( staticMetaObject.enumerator( index ).valueToKey( messageSorting ) ); + int index = staticMetaObject.indexOfEnumerator( "MessageSorting" ); + return QLatin1String( staticMetaObject.enumerator( index ).valueToKey( messageSorting ) ); } const QString SortOrder::nameForGroupSorting( GroupSorting groupSorting ) { - int index = staticMetaObject.indexOfEnumerator( "GroupSorting" ); - return QLatin1String( staticMetaObject.enumerator( index ).valueToKey( groupSorting ) ); + int index = staticMetaObject.indexOfEnumerator( "GroupSorting" ); + return QLatin1String( staticMetaObject.enumerator( index ).valueToKey( groupSorting ) ); } SortOrder::SortDirection SortOrder::sortDirectionForName( const QString& name ) { - int index = staticMetaObject.indexOfEnumerator( "SortDirection" ); - return static_cast( staticMetaObject.enumerator( index ).keyToValue( - name.toLatin1().constData() ) ); + int index = staticMetaObject.indexOfEnumerator( "SortDirection" ); + return static_cast( staticMetaObject.enumerator( index ).keyToValue( + name.toLatin1().constData() ) ); } SortOrder::MessageSorting SortOrder::messageSortingForName( const QString& name ) { - int index = staticMetaObject.indexOfEnumerator( "MessageSorting" ); - return static_cast( staticMetaObject.enumerator( index ).keyToValue( - name.toLatin1().constData() ) ); + int index = staticMetaObject.indexOfEnumerator( "MessageSorting" ); + return static_cast( staticMetaObject.enumerator( index ).keyToValue( + name.toLatin1().constData() ) ); } SortOrder::GroupSorting SortOrder::groupSortingForName( const QString& name ) { - int index = staticMetaObject.indexOfEnumerator( "GroupSorting" ); - return static_cast( staticMetaObject.enumerator( index ).keyToValue( - name.toLatin1().constData() ) ); + int index = staticMetaObject.indexOfEnumerator( "GroupSorting" ); + return static_cast( staticMetaObject.enumerator( index ).keyToValue( + name.toLatin1().constData() ) ); } #include "moc_sortorder.cpp" diff -Nru kdepim-4.12.97/messagelist/core/sortorder.h kdepim-4.13.0/messagelist/core/sortorder.h --- kdepim-4.12.97/messagelist/core/sortorder.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/sortorder.h 2014-04-10 07:40:20.000000000 +0000 @@ -36,12 +36,12 @@ */ class SortOrder { - Q_GADGET - Q_ENUMS( GroupSorting ) - Q_ENUMS( SortDirection ) - Q_ENUMS( MessageSorting ) + Q_GADGET + Q_ENUMS( GroupSorting ) + Q_ENUMS( SortDirection ) + Q_ENUMS( MessageSorting ) - public: +public: /** * How to sort the groups @@ -50,13 +50,13 @@ */ enum GroupSorting { - NoGroupSorting, ///< Don't sort the groups at all, add them as they come in - SortGroupsByDateTime, ///< Sort groups by date/time of the group - SortGroupsByDateTimeOfMostRecent, ///< Sort groups by date/time of the most recent message - SortGroupsBySenderOrReceiver, ///< Sort groups by sender or receiver (makes sense only with GroupBySenderOrReceiver) - SortGroupsBySender, ///< Sort groups by sender (makes sense only with GroupBySender) - SortGroupsByReceiver ///< Sort groups by receiver (makes sense only with GroupByReceiver) - // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) + NoGroupSorting, ///< Don't sort the groups at all, add them as they come in + SortGroupsByDateTime, ///< Sort groups by date/time of the group + SortGroupsByDateTimeOfMostRecent, ///< Sort groups by date/time of the most recent message + SortGroupsBySenderOrReceiver, ///< Sort groups by sender or receiver (makes sense only with GroupBySenderOrReceiver) + SortGroupsBySender, ///< Sort groups by sender (makes sense only with GroupBySender) + SortGroupsByReceiver ///< Sort groups by receiver (makes sense only with GroupByReceiver) + // Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) }; /** @@ -66,8 +66,8 @@ */ enum SortDirection { - Ascending, - Descending + Ascending, + Descending }; /** @@ -77,18 +77,18 @@ */ enum MessageSorting { - NoMessageSorting, ///< Don't sort the messages at all - SortMessagesByDateTime, ///< Sort the messages by date and time - SortMessagesByDateTimeOfMostRecent, ///< Sort the messages by date and time of the most recent message in subtree - SortMessagesBySenderOrReceiver, ///< Sort the messages by sender or receiver - SortMessagesBySender, ///< Sort the messages by sender - SortMessagesByReceiver, ///< Sort the messages by receiver - SortMessagesBySubject, ///< Sort the messages by subject - SortMessagesBySize, ///< Sort the messages by size - SortMessagesByActionItemStatus, ///< Sort the messages by the "Action Item" flag of status - SortMessagesByUnreadStatus, ///< Sort the messages by the "Unread" flags of status - SortMessagesByImportantStatus /// Sort the messages By "Important" flags of status - // Warning: Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) + NoMessageSorting, ///< Don't sort the messages at all + SortMessagesByDateTime, ///< Sort the messages by date and time + SortMessagesByDateTimeOfMostRecent, ///< Sort the messages by date and time of the most recent message in subtree + SortMessagesBySenderOrReceiver, ///< Sort the messages by sender or receiver + SortMessagesBySender, ///< Sort the messages by sender + SortMessagesByReceiver, ///< Sort the messages by receiver + SortMessagesBySubject, ///< Sort the messages by subject + SortMessagesBySize, ///< Sort the messages by size + SortMessagesByActionItemStatus, ///< Sort the messages by the "Action Item" flag of status + SortMessagesByUnreadStatus, ///< Sort the messages by the "Unread" flags of status + SortMessagesByImportantStatus /// Sort the messages By "Important" flags of status + // Warning: Never add enum entries in the middle: always add them at the end (numeric values are stored in configuration) }; explicit SortOrder(); @@ -97,7 +97,7 @@ * Returns the GroupSorting */ GroupSorting groupSorting() const - { return mGroupSorting; } + { return mGroupSorting; } /** * Sets the GroupSorting option. @@ -105,45 +105,45 @@ * is used in. */ void setGroupSorting( GroupSorting gs ) - { mGroupSorting = gs; } + { mGroupSorting = gs; } /** * Returns the current group SortDirection. */ SortDirection groupSortDirection() const - { return mGroupSortDirection; } + { return mGroupSortDirection; } /** * Sets the SortDirection for the groups. * Note that this option has no meaning if group sorting is set to NoGroupSorting. */ void setGroupSortDirection( SortDirection groupSortDirection ) - { mGroupSortDirection = groupSortDirection; } + { mGroupSortDirection = groupSortDirection; } - /** + /** * Returns the current message sorting option */ MessageSorting messageSorting() const - { return mMessageSorting; } + { return mMessageSorting; } - /** + /** * Sets the current message sorting option */ void setMessageSorting( MessageSorting ms ) - { mMessageSorting = ms; } + { mMessageSorting = ms; } - /** + /** * Returns the current message SortDirection. */ SortDirection messageSortDirection() const - { return mMessageSortDirection; } + { return mMessageSortDirection; } - /** + /** * Sets the SortDirection for the message. * Note that this option has no meaning if message sorting is set to NoMessageSorting. */ void setMessageSortDirection( SortDirection messageSortDirection ) - { mMessageSortDirection = messageSortDirection; } + { mMessageSortDirection = messageSortDirection; } /** * Enumerates the message sorting options compatible with the specified Threading setting. @@ -218,7 +218,7 @@ void writeConfig( KConfigGroup &conf, const QString &storageId, bool storageUsesPrivateSortOrder ) const; - private: +private: // Helper function to convert an enum value to a string and back static const QString nameForSortDirection( SortDirection sortDirection ); diff -Nru kdepim-4.12.97/messagelist/core/storagemodelbase.cpp kdepim-4.13.0/messagelist/core/storagemodelbase.cpp --- kdepim-4.12.97/messagelist/core/storagemodelbase.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/storagemodelbase.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -25,7 +25,7 @@ using namespace MessageList::Core; StorageModel::StorageModel( QObject * parent ) - : QAbstractItemModel( parent ) + : QAbstractItemModel( parent ) { } @@ -35,39 +35,39 @@ int StorageModel::initialUnreadRowCountGuess() const { - return rowCount( QModelIndex() ); + return rowCount( QModelIndex() ); } unsigned long StorageModel::preSelectedMessage() const { - const QString storageModelId = id(); - Q_ASSERT( !storageModelId.isEmpty() ); + const QString storageModelId = id(); + Q_ASSERT( !storageModelId.isEmpty() ); - KConfigGroup conf( Settings::self()->config(), - MessageList::Util::storageModelSelectedMessageGroup() ); + KConfigGroup conf( Settings::self()->config(), + MessageList::Util::storageModelSelectedMessageGroup() ); - // QVariant supports unsigned int OR unsigned long long int, NOT unsigned long int... doh... - qulonglong defValue = 0; + // QVariant supports unsigned int OR unsigned long long int, NOT unsigned long int... doh... + qulonglong defValue = 0; - return conf.readEntry( MessageList::Util::messageUniqueIdConfigName().arg( storageModelId ), defValue ); + return conf.readEntry( MessageList::Util::messageUniqueIdConfigName().arg( storageModelId ), defValue ); } void StorageModel::savePreSelectedMessage( unsigned long uniqueIdOfMessage ) { - const QString storageModelId = id(); - Q_ASSERT( !storageModelId.isEmpty() ); - - KConfigGroup conf( Settings::self()->config(), - MessageList::Util::storageModelSelectedMessageGroup() ); + const QString storageModelId = id(); + Q_ASSERT( !storageModelId.isEmpty() ); - if ( uniqueIdOfMessage ) - { - // QVariant supports unsigned int OR unsigned long long int, NOT unsigned long int... doh... - qulonglong val = uniqueIdOfMessage; + KConfigGroup conf( Settings::self()->config(), + MessageList::Util::storageModelSelectedMessageGroup() ); - conf.writeEntry( MessageList::Util::messageUniqueIdConfigName().arg( storageModelId ), val ); - } else - conf.deleteEntry( MessageList::Util::messageUniqueIdConfigName().arg( storageModelId ) ); + if ( uniqueIdOfMessage ) + { + // QVariant supports unsigned int OR unsigned long long int, NOT unsigned long int... doh... + qulonglong val = uniqueIdOfMessage; + + conf.writeEntry( MessageList::Util::messageUniqueIdConfigName().arg( storageModelId ), val ); + } else + conf.deleteEntry( MessageList::Util::messageUniqueIdConfigName().arg( storageModelId ) ); } diff -Nru kdepim-4.12.97/messagelist/core/storagemodelbase.h kdepim-4.13.0/messagelist/core/storagemodelbase.h --- kdepim-4.12.97/messagelist/core/storagemodelbase.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/storagemodelbase.h 2014-04-10 07:40:20.000000000 +0000 @@ -27,7 +27,7 @@ namespace Akonadi { - class MessageStatus; +class MessageStatus; } namespace MessageList @@ -44,44 +44,44 @@ */ class MESSAGELIST_EXPORT StorageModel : public QAbstractItemModel { - Q_OBJECT + Q_OBJECT public: - explicit StorageModel( QObject * parent = 0 ); - ~StorageModel(); + explicit StorageModel( QObject * parent = 0 ); + ~StorageModel(); - /** + /** * Returns an unique id for this Storage collection. * FIXME: This could be embedded in "name()" ? */ - virtual QString id() const = 0; + virtual QString id() const = 0; - /** + /** * Returns the unique id of the last selected message for this StorageModel. * Returns 0 if this value isn't stored in the configuration. */ - unsigned long preSelectedMessage() const; + unsigned long preSelectedMessage() const; - /** + /** * Stores in the unique id of the last selected message for the specified StorageModel. * The uniqueIdOfMessage may be 0 (which means that no selection shall be stored in the configuration). */ - void savePreSelectedMessage( unsigned long uniqueIdOfMessage ); + void savePreSelectedMessage( unsigned long uniqueIdOfMessage ); - /** + /** * Returns true if this StorageModel (folder) contains outbound messages and false otherwise. */ - virtual bool containsOutboundMessages() const = 0; + virtual bool containsOutboundMessages() const = 0; - /** + /** * Returns (a guess for) the number of unread messages: must be pessimistic (i.e. if you * have no idea just return rowCount(), which is also what the default implementation does). * This must be (and is) queried ONLY when the folder is first opened. It doesn't actually need * to keep the number of messages in sync as they later arrive to the storage. */ - virtual int initialUnreadRowCountGuess() const; + virtual int initialUnreadRowCountGuess() const; - /** + /** * This method should use the inner model implementation to fill in the * base data for the specified MessageItem from the underlying storage slot at * the specified row index. Must return true if the data fetch was succesfull @@ -90,47 +90,47 @@ * If bUseReceiver is true then the "senderOrReceiver" * field must be set to the receiver, otherwise it must be set to the sender. */ - virtual bool initializeMessageItem( MessageItem * it, int row, bool bUseReceiver ) const = 0; + virtual bool initializeMessageItem( MessageItem * it, int row, bool bUseReceiver ) const = 0; - enum ThreadingDataSubset - { - PerfectThreadingOnly, ///< Only the data for messageIdMD5 and inReplyToMD5 is needed - PerfectThreadingPlusReferences, ///< messageIdMD5, inReplyToMD5, referencesIdMD5 - PerfectThreadingReferencesAndSubject ///< All of the above plus subject stuff - }; + enum ThreadingDataSubset + { + PerfectThreadingOnly, ///< Only the data for messageIdMD5 and inReplyToMD5 is needed + PerfectThreadingPlusReferences, ///< messageIdMD5, inReplyToMD5, referencesIdMD5 + PerfectThreadingReferencesAndSubject ///< All of the above plus subject stuff + }; - /** + /** * This method should use the inner model implementation to fill in the specified subset of * threading data for the specified MessageItem from the underlying storage slot at * the specified row index. */ - virtual void fillMessageItemThreadingData( MessageItem * mi, int row, ThreadingDataSubset subset ) const = 0; + virtual void fillMessageItemThreadingData( MessageItem * mi, int row, ThreadingDataSubset subset ) const = 0; - /** + /** * This method should use the inner model implementation to re-fill the date, the status, * the encryption state, the signature state and eventually update the min/max dates * for the specified MessageItem from the underlying storage slot at the specified row index. */ - virtual void updateMessageItemData( MessageItem * mi, int row ) const = 0; + virtual void updateMessageItemData( MessageItem * mi, int row ) const = 0; - /** + /** * This method should use the inner model implementation to associate the new status * to the specified message item. The new status should be stored (but doesn't need * to be set as mi->status() itself as the caller is responsable for this). */ - virtual void setMessageItemStatus( MessageItem * mi, int row, const Akonadi::MessageStatus &status ) = 0; + virtual void setMessageItemStatus( MessageItem * mi, int row, const Akonadi::MessageStatus &status ) = 0; - /** + /** * Called by Model just before this StorageModel is attacched to it. */ - virtual void prepareForScan() = 0; + virtual void prepareForScan() = 0; - /** + /** * The implementation-specific mime data for this list of items. * Called when the user initiates a drag from the messagelist. */ - virtual QMimeData* mimeData( const QList< MessageItem* >& ) const = 0; - using QAbstractItemModel::mimeData; + virtual QMimeData* mimeData( const QList< MessageItem* >& ) const = 0; + using QAbstractItemModel::mimeData; }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/theme.cpp kdepim-4.13.0/messagelist/core/theme.cpp --- kdepim-4.12.97/messagelist/core/theme.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/theme.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -60,131 +60,131 @@ Theme::ContentItem::ContentItem( Type type ) - : mType( type ), mFlags( 0 ) + : mType( type ), mFlags( 0 ) { } Theme::ContentItem::ContentItem( const ContentItem &src ) - : mType( src.mType ), - mFlags( src.mFlags ), - mFont( src.mFont ), - mCustomColor( src.mCustomColor ) + : mType( src.mType ), + mFlags( src.mFlags ), + mFont( src.mFont ), + mCustomColor( src.mCustomColor ) { } QString Theme::ContentItem::description( Type type ) { - switch ( type ) - { + switch ( type ) + { case Subject: - return i18nc( "Description of Type Subject", "Subject" ); - break; + return i18nc( "Description of Type Subject", "Subject" ); + break; case Date: - return i18nc( "Description of Type Date", "Date" ); - break; + return i18nc( "Description of Type Date", "Date" ); + break; case SenderOrReceiver: - return i18n( "Sender/Receiver" ); - break; + return i18n( "Sender/Receiver" ); + break; case Sender: - return i18nc( "Description of Type Sender", "Sender" ); - break; + return i18nc( "Description of Type Sender", "Sender" ); + break; case Receiver: - return i18nc( "Description of Type Receiver", "Receiver" ); - break; + return i18nc( "Description of Type Receiver", "Receiver" ); + break; case Size: - return i18nc( "Description of Type Size", "Size" ); - break; + return i18nc( "Description of Type Size", "Size" ); + break; case ReadStateIcon: - return i18n( "Unread/Read Icon" ); - break; + return i18n( "Unread/Read Icon" ); + break; case AttachmentStateIcon: - return i18n( "Attachment Icon" ); - break; + return i18n( "Attachment Icon" ); + break; case RepliedStateIcon: - return i18n( "Replied/Forwarded Icon" ); - break; + return i18n( "Replied/Forwarded Icon" ); + break; case CombinedReadRepliedStateIcon: - return i18n( "Combined New/Unread/Read/Replied/Forwarded Icon" ); - break; + return i18n( "Combined New/Unread/Read/Replied/Forwarded Icon" ); + break; case ActionItemStateIcon: - return i18n( "Action Item Icon" ); - break; + return i18n( "Action Item Icon" ); + break; case ImportantStateIcon: - return i18n( "Important Icon" ); - break; + return i18n( "Important Icon" ); + break; case GroupHeaderLabel: - return i18n( "Group Header Label" ); - break; + return i18n( "Group Header Label" ); + break; case SpamHamStateIcon: - return i18n( "Spam/Ham Icon" ); - break; + return i18n( "Spam/Ham Icon" ); + break; case WatchedIgnoredStateIcon: - return i18n( "Watched/Ignored Icon" ); - break; + return i18n( "Watched/Ignored Icon" ); + break; case ExpandedStateIcon: - return i18n( "Group Header Expand/Collapse Icon" ); - break; + return i18n( "Group Header Expand/Collapse Icon" ); + break; case EncryptionStateIcon: - return i18n( "Encryption State Icon" ); - break; + return i18n( "Encryption State Icon" ); + break; case SignatureStateIcon: - return i18n( "Signature State Icon" ); - break; + return i18n( "Signature State Icon" ); + break; case VerticalLine: - return i18n( "Vertical Separation Line" ); - break; + return i18n( "Vertical Separation Line" ); + break; case HorizontalSpacer: - return i18n( "Horizontal Spacer" ); - break; + return i18n( "Horizontal Spacer" ); + break; case MostRecentDate: - return i18n( "Max Date" ); - break; + return i18n( "Max Date" ); + break; case TagList: - return i18n( "Message Tags" ); - break; + return i18n( "Message Tags" ); + break; case AnnotationIcon: - return i18n( "Note Icon" ); + return i18n( "Note Icon" ); case InvitationIcon: - return i18n( "Invitation Icon" ); + return i18n( "Invitation Icon" ); default: - return i18nc( "Description for an Unknown Type", "Unknown" ); - break; - } + return i18nc( "Description for an Unknown Type", "Unknown" ); + break; + } } bool Theme::ContentItem::applicableToMessageItems( Type type ) { - return ( static_cast< int >( type ) & ApplicableToMessageItems ); + return ( static_cast< int >( type ) & ApplicableToMessageItems ); } bool Theme::ContentItem::applicableToGroupHeaderItems( Type type ) { - return ( static_cast< int >( type ) & ApplicableToGroupHeaderItems ); + return ( static_cast< int >( type ) & ApplicableToGroupHeaderItems ); } void Theme::ContentItem::setFont( const QFont &font ) { - mFont = font; - mFontKey = font.key(); + mFont = font; + mFontKey = font.key(); } void Theme::ContentItem::save( QDataStream &stream ) const { - stream << (int)mType; - stream << mFlags; - stream << mFont; - stream << mCustomColor; + stream << (int)mType; + stream << mFlags; + stream << mFont; + stream << mCustomColor; } bool Theme::ContentItem::load( QDataStream &stream, int /*themeVersion*/ ) { - int val; + int val; - stream >> val; - mType = static_cast< Type >( val ); - switch( mType ) - { + stream >> val; + mType = static_cast< Type >( val ); + switch( mType ) + { case Subject: case Date: case SenderOrReceiver: @@ -209,23 +209,23 @@ case TagList: case AnnotationIcon: case InvitationIcon: - // ok - break; + // ok + break; default: - kDebug() << "Invalid content item type"; - return false; // b0rken - break; - } - - stream >> mFlags; - stream >> mFont; - stream >> mCustomColor; - if ( mFlags & UseCustomColor ) - { - if ( !mCustomColor.isValid() ) - mFlags &= ~UseCustomColor; - } - return true; + kDebug() << "Invalid content item type"; + return false; // b0rken + break; + } + + stream >> mFlags; + stream >> mFont; + stream >> mCustomColor; + if ( mFlags & UseCustomColor ) + { + if ( !mCustomColor.isValid() ) + mFlags &= ~UseCustomColor; + } + return true; } @@ -237,172 +237,172 @@ Theme::Row::Row( const Row &src ) { - QList< ContentItem * >::ConstIterator end( src.mLeftItems.constEnd() ); - for ( QList< ContentItem * >::ConstIterator it = src.mLeftItems.constBegin(); it != end ; ++it ) - addLeftItem( new ContentItem( *( *it ) ) ); - - end= src.mRightItems.constEnd(); - for ( QList< ContentItem * >::ConstIterator it = src.mRightItems.constBegin(); it != end ; ++it ) - addRightItem( new ContentItem( *( *it ) ) ); + QList< ContentItem * >::ConstIterator end( src.mLeftItems.constEnd() ); + for ( QList< ContentItem * >::ConstIterator it = src.mLeftItems.constBegin(); it != end ; ++it ) + addLeftItem( new ContentItem( *( *it ) ) ); + + end= src.mRightItems.constEnd(); + for ( QList< ContentItem * >::ConstIterator it = src.mRightItems.constBegin(); it != end ; ++it ) + addRightItem( new ContentItem( *( *it ) ) ); } Theme::Row::~Row() { - removeAllLeftItems(); - removeAllRightItems(); + removeAllLeftItems(); + removeAllRightItems(); } void Theme::Row::removeAllLeftItems() { - while( !mLeftItems.isEmpty() ) - delete mLeftItems.takeFirst(); + while( !mLeftItems.isEmpty() ) + delete mLeftItems.takeFirst(); } void Theme::Row::removeAllRightItems() { - while( !mRightItems.isEmpty() ) - delete mRightItems.takeFirst(); + while( !mRightItems.isEmpty() ) + delete mRightItems.takeFirst(); } void Theme::Row::insertLeftItem( int idx, ContentItem * item ) { - if ( idx >= mLeftItems.count() ) - { - mLeftItems.append( item ); - return; - } - mLeftItems.insert( idx, item ); + if ( idx >= mLeftItems.count() ) + { + mLeftItems.append( item ); + return; + } + mLeftItems.insert( idx, item ); } void Theme::Row::insertRightItem( int idx, ContentItem * item ) { - if ( idx >= mRightItems.count() ) - { - mRightItems.append( item ); - return; - } - mRightItems.insert( idx, item ); + if ( idx >= mRightItems.count() ) + { + mRightItems.append( item ); + return; + } + mRightItems.insert( idx, item ); } bool Theme::Row::containsTextItems() const { - QList< ContentItem * >::ConstIterator end( mLeftItems.constEnd() ); - for ( QList< ContentItem * >::ConstIterator it = mLeftItems.constBegin(); it != end ; ++it ) - { - if ( ( *it )->displaysText() ) - return true; - } - end = mRightItems.constEnd(); - for ( QList< ContentItem * >::ConstIterator it = mRightItems.constBegin(); it != end ; ++it ) - { - if ( ( *it )->displaysText() ) - return true; - } - return false; + QList< ContentItem * >::ConstIterator end( mLeftItems.constEnd() ); + for ( QList< ContentItem * >::ConstIterator it = mLeftItems.constBegin(); it != end ; ++it ) + { + if ( ( *it )->displaysText() ) + return true; + } + end = mRightItems.constEnd(); + for ( QList< ContentItem * >::ConstIterator it = mRightItems.constBegin(); it != end ; ++it ) + { + if ( ( *it )->displaysText() ) + return true; + } + return false; } void Theme::Row::save( QDataStream &stream ) const { - stream << (int)mLeftItems.count(); + stream << (int)mLeftItems.count(); - int cnt = mLeftItems.count(); + int cnt = mLeftItems.count(); - for ( int i = 0; i < cnt ; ++i ) - { - ContentItem * ci = mLeftItems.at( i ); - ci->save( stream ); - } + for ( int i = 0; i < cnt ; ++i ) + { + ContentItem * ci = mLeftItems.at( i ); + ci->save( stream ); + } - stream << (int)mRightItems.count(); + stream << (int)mRightItems.count(); - cnt = mRightItems.count(); + cnt = mRightItems.count(); - for ( int i = 0; i < cnt ; ++i ) - { - ContentItem * ci = mRightItems.at( i ); - ci->save( stream ); - } + for ( int i = 0; i < cnt ; ++i ) + { + ContentItem * ci = mRightItems.at( i ); + ci->save( stream ); + } } bool Theme::Row::LoadContentItem(int val, QDataStream &stream, int themeVersion, bool leftItem) { if ( ( val < 0 ) || ( val > 50 ) ) - return false; // senseless + return false; // senseless // FIXME: Remove code duplication here for ( int i = 0; i < val ; ++i ) { - ContentItem * ci = new ContentItem( ContentItem::Subject ); // dummy type - if ( !ci->load( stream, themeVersion ) ) - { - kDebug() << "Left content item loading failed"; - delete ci; - return false; - } - if (leftItem) - addLeftItem( ci ); - else - addRightItem( ci ); - - // Add the annotation item next to the attachment icon, so that users upgrading from old - // versions don't manually need to set this. - // Don't do this for the stand-alone attchment column. - if ( ci->type() == ContentItem::AttachmentStateIcon && - themeVersion < gThemeMinimumVersionWithAnnotationIcon && - val > 1 ) { - kDebug() << "Old theme version detected, adding annotation item next to attachment icon."; - ContentItem *annotationItem = new ContentItem( ContentItem::AnnotationIcon ) ; - annotationItem->setHideWhenDisabled( true ); + ContentItem * ci = new ContentItem( ContentItem::Subject ); // dummy type + if ( !ci->load( stream, themeVersion ) ) + { + kDebug() << "Left content item loading failed"; + delete ci; + return false; + } if (leftItem) - addLeftItem( annotationItem ); + addLeftItem( ci ); else - addRightItem( annotationItem ); - } + addRightItem( ci ); - // Same as above, for the invitation icon - if ( ci->type() == ContentItem::AttachmentStateIcon && - themeVersion < gThemeMinimumVersionWithInvitationIcon && - val > 1 ) { - kDebug() << "Old theme version detected, adding invitation item next to attachment icon."; - ContentItem *invitationItem = new ContentItem( ContentItem::InvitationIcon ) ; - invitationItem->setHideWhenDisabled( true ); - if (leftItem) - addLeftItem( invitationItem ); - else - addRightItem( invitationItem ); - } + // Add the annotation item next to the attachment icon, so that users upgrading from old + // versions don't manually need to set this. + // Don't do this for the stand-alone attchment column. + if ( ci->type() == ContentItem::AttachmentStateIcon && + themeVersion < gThemeMinimumVersionWithAnnotationIcon && + val > 1 ) { + kDebug() << "Old theme version detected, adding annotation item next to attachment icon."; + ContentItem *annotationItem = new ContentItem( ContentItem::AnnotationIcon ) ; + annotationItem->setHideWhenDisabled( true ); + if (leftItem) + addLeftItem( annotationItem ); + else + addRightItem( annotationItem ); + } + + // Same as above, for the invitation icon + if ( ci->type() == ContentItem::AttachmentStateIcon && + themeVersion < gThemeMinimumVersionWithInvitationIcon && + val > 1 ) { + kDebug() << "Old theme version detected, adding invitation item next to attachment icon."; + ContentItem *invitationItem = new ContentItem( ContentItem::InvitationIcon ) ; + invitationItem->setHideWhenDisabled( true ); + if (leftItem) + addLeftItem( invitationItem ); + else + addRightItem( invitationItem ); + } } return true; } bool Theme::Row::load( QDataStream &stream, int themeVersion ) { - removeAllLeftItems(); - removeAllRightItems(); + removeAllLeftItems(); + removeAllRightItems(); - int val; + int val; - // left item count + // left item count - stream >> val; - if (!LoadContentItem(val, stream, themeVersion, true)) - return false; + stream >> val; + if (!LoadContentItem(val, stream, themeVersion, true)) + return false; - // right item count + // right item count - stream >> val; + stream >> val; - if (!LoadContentItem(val, stream, themeVersion, false)) - return false; + if (!LoadContentItem(val, stream, themeVersion, false)) + return false; - return true; + return true; } Theme::Column::SharedRuntimeData::SharedRuntimeData( bool currentlyVisible, int currentWidth ) - : mReferences( 0 ), mCurrentlyVisible( currentlyVisible ), mCurrentWidth( currentWidth ) + : mReferences( 0 ), mCurrentlyVisible( currentlyVisible ), mCurrentWidth( currentWidth ) { } @@ -412,423 +412,423 @@ void Theme::Column::SharedRuntimeData::addReference() { - mReferences++; + mReferences++; } bool Theme::Column::SharedRuntimeData::deleteReference() { - mReferences--; - Q_ASSERT( mReferences >= 0 ); - return mReferences > 0; + mReferences--; + Q_ASSERT( mReferences >= 0 ); + return mReferences > 0; } void Theme::Column::SharedRuntimeData::save( QDataStream &stream ) const { - stream << mCurrentlyVisible; - stream << mCurrentWidth; + stream << mCurrentlyVisible; + stream << mCurrentWidth; } bool Theme::Column::SharedRuntimeData::load( QDataStream &stream, int /* themeVersion */ ) { - stream >> mCurrentlyVisible; - stream >> mCurrentWidth; - if ( mCurrentWidth > 10000 ) - { - kDebug() << "Theme has insane column width " << mCurrentWidth << " chopping to 100"; - mCurrentWidth = 100; // avoid really insane values - } - return (mCurrentWidth >= -1); + stream >> mCurrentlyVisible; + stream >> mCurrentWidth; + if ( mCurrentWidth > 10000 ) + { + kDebug() << "Theme has insane column width " << mCurrentWidth << " chopping to 100"; + mCurrentWidth = 100; // avoid really insane values + } + return (mCurrentWidth >= -1); } Theme::Column::Column() - : mVisibleByDefault( true ), - mIsSenderOrReceiver( false ), - mMessageSorting( SortOrder::NoMessageSorting ) + : mVisibleByDefault( true ), + mIsSenderOrReceiver( false ), + mMessageSorting( SortOrder::NoMessageSorting ) { - mSharedRuntimeData = new SharedRuntimeData( true, -1 ); - mSharedRuntimeData->addReference(); + mSharedRuntimeData = new SharedRuntimeData( true, -1 ); + mSharedRuntimeData->addReference(); } Theme::Column::Column( const Column &src ) { - mLabel = src.mLabel; - mPixmapName = src.mPixmapName; - mVisibleByDefault = src.mVisibleByDefault; - mIsSenderOrReceiver = src.mIsSenderOrReceiver; - mMessageSorting = src.mMessageSorting; - - mSharedRuntimeData = src.mSharedRuntimeData; - mSharedRuntimeData->addReference(); - QList< Row * >::ConstIterator end( src.mMessageRows.constEnd() ); - for ( QList< Row * >::ConstIterator it = src.mMessageRows.constBegin(); it != end ; ++it ) - addMessageRow( new Row( *( *it ) ) ); - - end = src.mGroupHeaderRows.constEnd(); - for ( QList< Row * >::ConstIterator it = src.mGroupHeaderRows.constBegin(); it != end ; ++it ) - addGroupHeaderRow( new Row( *( *it ) ) ); + mLabel = src.mLabel; + mPixmapName = src.mPixmapName; + mVisibleByDefault = src.mVisibleByDefault; + mIsSenderOrReceiver = src.mIsSenderOrReceiver; + mMessageSorting = src.mMessageSorting; + + mSharedRuntimeData = src.mSharedRuntimeData; + mSharedRuntimeData->addReference(); + QList< Row * >::ConstIterator end( src.mMessageRows.constEnd() ); + for ( QList< Row * >::ConstIterator it = src.mMessageRows.constBegin(); it != end ; ++it ) + addMessageRow( new Row( *( *it ) ) ); + + end = src.mGroupHeaderRows.constEnd(); + for ( QList< Row * >::ConstIterator it = src.mGroupHeaderRows.constBegin(); it != end ; ++it ) + addGroupHeaderRow( new Row( *( *it ) ) ); } Theme::Column::~Column() { - removeAllMessageRows(); - removeAllGroupHeaderRows(); - if( !( mSharedRuntimeData->deleteReference() ) ) - delete mSharedRuntimeData; + removeAllMessageRows(); + removeAllGroupHeaderRows(); + if( !( mSharedRuntimeData->deleteReference() ) ) + delete mSharedRuntimeData; } void Theme::Column::detach() { - if( mSharedRuntimeData->referenceCount() < 2 ) - return; // nothing to detach - mSharedRuntimeData->deleteReference(); + if( mSharedRuntimeData->referenceCount() < 2 ) + return; // nothing to detach + mSharedRuntimeData->deleteReference(); - mSharedRuntimeData = new SharedRuntimeData( mVisibleByDefault, -1 ); - mSharedRuntimeData->addReference(); + mSharedRuntimeData = new SharedRuntimeData( mVisibleByDefault, -1 ); + mSharedRuntimeData->addReference(); } void Theme::Column::removeAllMessageRows() { - while ( !mMessageRows.isEmpty() ) - delete mMessageRows.takeFirst(); + while ( !mMessageRows.isEmpty() ) + delete mMessageRows.takeFirst(); } void Theme::Column::removeAllGroupHeaderRows() { - while ( !mGroupHeaderRows.isEmpty() ) - delete mGroupHeaderRows.takeFirst(); + while ( !mGroupHeaderRows.isEmpty() ) + delete mGroupHeaderRows.takeFirst(); } void Theme::Column::insertMessageRow( int idx, Row * row ) { - if ( idx >= mMessageRows.count() ) - { - mMessageRows.append( row ); - return; - } - mMessageRows.insert( idx, row ); + if ( idx >= mMessageRows.count() ) + { + mMessageRows.append( row ); + return; + } + mMessageRows.insert( idx, row ); } void Theme::Column::insertGroupHeaderRow( int idx, Row * row ) { - if ( idx >= mGroupHeaderRows.count() ) - { - mGroupHeaderRows.append( row ); - return; - } - mGroupHeaderRows.insert( idx, row ); + if ( idx >= mGroupHeaderRows.count() ) + { + mGroupHeaderRows.append( row ); + return; + } + mGroupHeaderRows.insert( idx, row ); } bool Theme::Column::containsTextItems() const { - QList< Row * >::ConstIterator end( mMessageRows.constEnd() ); - for ( QList< Row * >::ConstIterator it = mMessageRows.constBegin(); it != end ; ++it ) - { - if ( ( *it )->containsTextItems() ) - return true; - } - end = mGroupHeaderRows.constEnd(); - for ( QList< Row * >::ConstIterator it = mGroupHeaderRows.constBegin(); it != end ; ++it ) - { - if ( ( *it )->containsTextItems() ) - return true; - } - return false; + QList< Row * >::ConstIterator end( mMessageRows.constEnd() ); + for ( QList< Row * >::ConstIterator it = mMessageRows.constBegin(); it != end ; ++it ) + { + if ( ( *it )->containsTextItems() ) + return true; + } + end = mGroupHeaderRows.constEnd(); + for ( QList< Row * >::ConstIterator it = mGroupHeaderRows.constBegin(); it != end ; ++it ) + { + if ( ( *it )->containsTextItems() ) + return true; + } + return false; } void Theme::Column::save( QDataStream &stream ) const { - stream << mLabel; - stream << mPixmapName; - stream << mVisibleByDefault; - stream << mIsSenderOrReceiver; - stream << (int)mMessageSorting; - - stream << (int)mGroupHeaderRows.count(); - - int cnt = mGroupHeaderRows.count(); - - for ( int i = 0; i < cnt ; ++i ) - { - Row * row = mGroupHeaderRows.at( i ); - row->save( stream ); - } - - cnt = mMessageRows.count(); - stream << (int)cnt; - - for ( int i = 0; i < cnt ; ++i ) - { - Row * row = mMessageRows.at( i ); - row->save( stream ); - } + stream << mLabel; + stream << mPixmapName; + stream << mVisibleByDefault; + stream << mIsSenderOrReceiver; + stream << (int)mMessageSorting; - // added in version 0x1014 - mSharedRuntimeData->save( stream ); + stream << (int)mGroupHeaderRows.count(); + + int cnt = mGroupHeaderRows.count(); + + for ( int i = 0; i < cnt ; ++i ) + { + Row * row = mGroupHeaderRows.at( i ); + row->save( stream ); + } + + cnt = mMessageRows.count(); + stream << (int)cnt; + + for ( int i = 0; i < cnt ; ++i ) + { + Row * row = mMessageRows.at( i ); + row->save( stream ); + } + + // added in version 0x1014 + mSharedRuntimeData->save( stream ); } bool Theme::Column::load( QDataStream &stream, int themeVersion ) { - removeAllGroupHeaderRows(); - removeAllMessageRows(); + removeAllGroupHeaderRows(); + removeAllMessageRows(); - stream >> mLabel; + stream >> mLabel; - if ( themeVersion >= gThemeMinimumVersionWithColumnIcon ) - stream >> mPixmapName; + if ( themeVersion >= gThemeMinimumVersionWithColumnIcon ) + stream >> mPixmapName; - stream >> mVisibleByDefault; - stream >> mIsSenderOrReceiver; + stream >> mVisibleByDefault; + stream >> mIsSenderOrReceiver; - int val; + int val; - stream >> val; - mMessageSorting = static_cast< SortOrder::MessageSorting >( val ); - if ( !SortOrder::isValidMessageSorting( mMessageSorting ) ) - { - kDebug() << "Invalid message sorting"; - return false; - } + stream >> val; + mMessageSorting = static_cast< SortOrder::MessageSorting >( val ); + if ( !SortOrder::isValidMessageSorting( mMessageSorting ) ) + { + kDebug() << "Invalid message sorting"; + return false; + } + + if ( themeVersion < gThemeMinimumVersionWithSortingByUnreadStatusAllowed ) + { + // The default "Classic" theme "Unread" column had sorting disabled here. + // We want to be nice to the existing users and automatically set + // the new sorting method for this column (so they don't have to make the + // complex steps to set it by themselves). + // This piece of code isn't strictly required: it's just a niceness :) + if ( ( mMessageSorting == SortOrder::NoMessageSorting ) && ( mLabel == i18n( "Unread" ) ) ) + mMessageSorting = SortOrder::SortMessagesByUnreadStatus; + } - if ( themeVersion < gThemeMinimumVersionWithSortingByUnreadStatusAllowed ) - { - // The default "Classic" theme "Unread" column had sorting disabled here. - // We want to be nice to the existing users and automatically set - // the new sorting method for this column (so they don't have to make the - // complex steps to set it by themselves). - // This piece of code isn't strictly required: it's just a niceness :) - if ( ( mMessageSorting == SortOrder::NoMessageSorting ) && ( mLabel == i18n( "Unread" ) ) ) - mMessageSorting = SortOrder::SortMessagesByUnreadStatus; - } - - // group header row count - stream >> val; - - if ( ( val < 0 ) || ( val > 50 ) ) - { - kDebug() << "Invalid group header row count"; - return false; // senseless - } - - for ( int i = 0; i < val ; ++i ) - { - Row * row = new Row(); - if ( !row->load( stream, themeVersion ) ) - { - kDebug() << "Group header row loading failed"; - delete row; - return false; - } - addGroupHeaderRow( row ); - } - - // message row count - stream >> val; - - if ( ( val < 0 ) || ( val > 50 ) ) - { - kDebug() << "Invalid message row count"; - return false; // senseless - } - - for ( int i = 0; i < val ; ++i ) - { - Row * row = new Row(); - if ( !row->load( stream, themeVersion ) ) - { - kDebug() << "Message row loading failed"; - delete row; - return false; - } - addMessageRow( row ); - } - - if ( themeVersion >= gThemeMinimumVersionWithColumnRuntimeData ) - { - // starting with version 0x1014 we have runtime data too - if( !mSharedRuntimeData->load( stream, themeVersion ) ) - { - kDebug() << "Shared runtime data loading failed"; - return false; - } - } else { - // assume default shared data - mSharedRuntimeData->setCurrentlyVisible( mVisibleByDefault ); - mSharedRuntimeData->setCurrentWidth( -1 ); - } + // group header row count + stream >> val; - return true; + if ( ( val < 0 ) || ( val > 50 ) ) + { + kDebug() << "Invalid group header row count"; + return false; // senseless + } + + for ( int i = 0; i < val ; ++i ) + { + Row * row = new Row(); + if ( !row->load( stream, themeVersion ) ) + { + kDebug() << "Group header row loading failed"; + delete row; + return false; + } + addGroupHeaderRow( row ); + } + + // message row count + stream >> val; + + if ( ( val < 0 ) || ( val > 50 ) ) + { + kDebug() << "Invalid message row count"; + return false; // senseless + } + + for ( int i = 0; i < val ; ++i ) + { + Row * row = new Row(); + if ( !row->load( stream, themeVersion ) ) + { + kDebug() << "Message row loading failed"; + delete row; + return false; + } + addMessageRow( row ); + } + + if ( themeVersion >= gThemeMinimumVersionWithColumnRuntimeData ) + { + // starting with version 0x1014 we have runtime data too + if( !mSharedRuntimeData->load( stream, themeVersion ) ) + { + kDebug() << "Shared runtime data loading failed"; + return false; + } + } else { + // assume default shared data + mSharedRuntimeData->setCurrentlyVisible( mVisibleByDefault ); + mSharedRuntimeData->setCurrentWidth( -1 ); + } + + return true; } Theme::Theme() - : OptionSet() + : OptionSet() { - mGroupHeaderBackgroundMode = AutoColor; - mViewHeaderPolicy = ShowHeaderAlways; - mIconSize = gThemeDefaultIconSize; - mGroupHeaderBackgroundStyle = StyledJoinedRect; + mGroupHeaderBackgroundMode = AutoColor; + mViewHeaderPolicy = ShowHeaderAlways; + mIconSize = gThemeDefaultIconSize; + mGroupHeaderBackgroundStyle = StyledJoinedRect; } Theme::Theme( const QString &name, const QString &description, bool readOnly ) - : OptionSet( name, description, readOnly ) + : OptionSet( name, description, readOnly ) { - mGroupHeaderBackgroundMode = AutoColor; - mGroupHeaderBackgroundStyle = StyledJoinedRect; - mViewHeaderPolicy = ShowHeaderAlways; - mIconSize = gThemeDefaultIconSize; + mGroupHeaderBackgroundMode = AutoColor; + mGroupHeaderBackgroundStyle = StyledJoinedRect; + mViewHeaderPolicy = ShowHeaderAlways; + mIconSize = gThemeDefaultIconSize; } Theme::Theme( const Theme &src ) - : OptionSet( src ) + : OptionSet( src ) { - mGroupHeaderBackgroundMode = src.mGroupHeaderBackgroundMode; - mGroupHeaderBackgroundColor = src.mGroupHeaderBackgroundColor; - mGroupHeaderBackgroundStyle = src.mGroupHeaderBackgroundStyle; - mViewHeaderPolicy = src.mViewHeaderPolicy; - mIconSize = src.mIconSize; - QList< Column * >::ConstIterator end( src.mColumns.constEnd() ); - for ( QList< Column * >::ConstIterator it = src.mColumns.constBegin(); it != end ; ++it ) - addColumn( new Column( *( *it ) ) ); + mGroupHeaderBackgroundMode = src.mGroupHeaderBackgroundMode; + mGroupHeaderBackgroundColor = src.mGroupHeaderBackgroundColor; + mGroupHeaderBackgroundStyle = src.mGroupHeaderBackgroundStyle; + mViewHeaderPolicy = src.mViewHeaderPolicy; + mIconSize = src.mIconSize; + QList< Column * >::ConstIterator end( src.mColumns.constEnd() ); + for ( QList< Column * >::ConstIterator it = src.mColumns.constBegin(); it != end ; ++it ) + addColumn( new Column( *( *it ) ) ); } Theme::~Theme() { - removeAllColumns(); + removeAllColumns(); } void Theme::detach() { - QList< Column * >::ConstIterator end( mColumns.constEnd() ); - for ( QList< Column * >::ConstIterator it = mColumns.constBegin(); it != end ; ++it ) - ( *it )->detach(); + QList< Column * >::ConstIterator end( mColumns.constEnd() ); + for ( QList< Column * >::ConstIterator it = mColumns.constBegin(); it != end ; ++it ) + ( *it )->detach(); } void Theme::resetColumnState() { - QList< Column * >::ConstIterator end( mColumns.constEnd() ); - for ( QList< Column * >::ConstIterator it = mColumns.constBegin(); it != end ; ++it ) - { - ( *it )->setCurrentlyVisible( ( *it )->visibleByDefault() ); - ( *it )->setCurrentWidth( -1 ); - } + QList< Column * >::ConstIterator end( mColumns.constEnd() ); + for ( QList< Column * >::ConstIterator it = mColumns.constBegin(); it != end ; ++it ) + { + ( *it )->setCurrentlyVisible( ( *it )->visibleByDefault() ); + ( *it )->setCurrentWidth( -1 ); + } } void Theme::resetColumnSizes() { - QList< Column * >::ConstIterator end( mColumns.constEnd() ); - for ( QList< Column * >::ConstIterator it = mColumns.constBegin(); it != end; ++it ) - ( *it )->setCurrentWidth( -1 ); + QList< Column * >::ConstIterator end( mColumns.constEnd() ); + for ( QList< Column * >::ConstIterator it = mColumns.constBegin(); it != end; ++it ) + ( *it )->setCurrentWidth( -1 ); } void Theme::removeAllColumns() { - while ( !mColumns.isEmpty() ) - delete mColumns.takeFirst(); + while ( !mColumns.isEmpty() ) + delete mColumns.takeFirst(); } void Theme::insertColumn( int idx, Column * column ) { - if ( idx >= mColumns.count() ) - { - mColumns.append( column ); - return; - } - mColumns.insert( idx, column ); + if ( idx >= mColumns.count() ) + { + mColumns.append( column ); + return; + } + mColumns.insert( idx, column ); } void Theme::moveColumn(int idx, int newPosition) { - if ( (newPosition >= mColumns.count()) || newPosition < 0 ) - return; - mColumns.move( idx, newPosition ); + if ( (newPosition >= mColumns.count()) || newPosition < 0 ) + return; + mColumns.move( idx, newPosition ); } void Theme::setGroupHeaderBackgroundMode( GroupHeaderBackgroundMode bm ) { - mGroupHeaderBackgroundMode = bm; - if ( ( bm == CustomColor ) && !mGroupHeaderBackgroundColor.isValid() ) - mGroupHeaderBackgroundColor = QColor( 127, 127, 127 ); // something neutral + mGroupHeaderBackgroundMode = bm; + if ( ( bm == CustomColor ) && !mGroupHeaderBackgroundColor.isValid() ) + mGroupHeaderBackgroundColor = QColor( 127, 127, 127 ); // something neutral } QList< QPair< QString, int > > Theme::enumerateViewHeaderPolicyOptions() { - QList< QPair< QString, int > > ret; - ret.append( QPair< QString, int >( i18n( "Never Show" ), NeverShowHeader ) ); - ret.append( QPair< QString, int >( i18n( "Always Show" ), ShowHeaderAlways ) ); - return ret; + QList< QPair< QString, int > > ret; + ret.append( QPair< QString, int >( i18n( "Never Show" ), NeverShowHeader ) ); + ret.append( QPair< QString, int >( i18n( "Always Show" ), ShowHeaderAlways ) ); + return ret; } QList< QPair< QString, int > > Theme::enumerateGroupHeaderBackgroundStyles() { - QList< QPair< QString, int > > ret; - ret.append( QPair< QString, int >( i18n( "Plain Rectangles" ), PlainRect ) ); - ret.append( QPair< QString, int >( i18n( "Plain Joined Rectangle" ), PlainJoinedRect ) ); - ret.append( QPair< QString, int >( i18n( "Rounded Rectangles" ), RoundedRect ) ); - ret.append( QPair< QString, int >( i18n( "Rounded Joined Rectangle" ), RoundedJoinedRect ) ); - ret.append( QPair< QString, int >( i18n( "Gradient Rectangles" ), GradientRect ) ); - ret.append( QPair< QString, int >( i18n( "Gradient Joined Rectangle" ), GradientJoinedRect ) ); - ret.append( QPair< QString, int >( i18n( "Styled Rectangles" ), StyledRect ) ); - ret.append( QPair< QString, int >( i18n( "Styled Joined Rectangles" ), StyledJoinedRect ) ); + QList< QPair< QString, int > > ret; + ret.append( QPair< QString, int >( i18n( "Plain Rectangles" ), PlainRect ) ); + ret.append( QPair< QString, int >( i18n( "Plain Joined Rectangle" ), PlainJoinedRect ) ); + ret.append( QPair< QString, int >( i18n( "Rounded Rectangles" ), RoundedRect ) ); + ret.append( QPair< QString, int >( i18n( "Rounded Joined Rectangle" ), RoundedJoinedRect ) ); + ret.append( QPair< QString, int >( i18n( "Gradient Rectangles" ), GradientRect ) ); + ret.append( QPair< QString, int >( i18n( "Gradient Joined Rectangle" ), GradientJoinedRect ) ); + ret.append( QPair< QString, int >( i18n( "Styled Rectangles" ), StyledRect ) ); + ret.append( QPair< QString, int >( i18n( "Styled Joined Rectangles" ), StyledJoinedRect ) ); - return ret; + return ret; } void Theme::setIconSize( int iconSize ) { - mIconSize = iconSize; - if ( ( mIconSize < 8 ) || ( mIconSize > 64 ) ) - mIconSize = gThemeDefaultIconSize; + mIconSize = iconSize; + if ( ( mIconSize < 8 ) || ( mIconSize > 64 ) ) + mIconSize = gThemeDefaultIconSize; } bool Theme::load( QDataStream &stream ) { - removeAllColumns(); + removeAllColumns(); - int themeVersion; + int themeVersion; - stream >> themeVersion; + stream >> themeVersion; - // We support themes starting at version gThemeMinimumSupportedVersion (0x1013 actually) + // We support themes starting at version gThemeMinimumSupportedVersion (0x1013 actually) - if ( - ( themeVersion > gThemeCurrentVersion ) || - ( themeVersion < gThemeMinimumSupportedVersion ) - ) - { - kDebug() << "Invalid theme version"; - return false; // b0rken (invalid version) - } + if ( + ( themeVersion > gThemeCurrentVersion ) || + ( themeVersion < gThemeMinimumSupportedVersion ) + ) + { + kDebug() << "Invalid theme version"; + return false; // b0rken (invalid version) + } - int val; + int val; - stream >> val; - mGroupHeaderBackgroundMode = (GroupHeaderBackgroundMode)val; - switch(mGroupHeaderBackgroundMode) - { + stream >> val; + mGroupHeaderBackgroundMode = (GroupHeaderBackgroundMode)val; + switch(mGroupHeaderBackgroundMode) + { case Transparent: case AutoColor: case CustomColor: - // ok - break; + // ok + break; default: - kDebug() << "Invalid theme group header background mode"; - return false; // b0rken - break; - } - - stream >> mGroupHeaderBackgroundColor; - - stream >> val; - mGroupHeaderBackgroundStyle = (GroupHeaderBackgroundStyle)val; - switch(mGroupHeaderBackgroundStyle) - { + kDebug() << "Invalid theme group header background mode"; + return false; // b0rken + break; + } + + stream >> mGroupHeaderBackgroundColor; + + stream >> val; + mGroupHeaderBackgroundStyle = (GroupHeaderBackgroundStyle)val; + switch(mGroupHeaderBackgroundStyle) + { case PlainRect: case PlainJoinedRect: case RoundedRect: @@ -837,76 +837,76 @@ case GradientJoinedRect: case StyledRect: case StyledJoinedRect: - // ok - break; + // ok + break; default: - kDebug() << "Invalid theme group header background style"; - return false; // b0rken - break; - } - - stream >> val; - mViewHeaderPolicy = (ViewHeaderPolicy)val; - switch(mViewHeaderPolicy) - { + kDebug() << "Invalid theme group header background style"; + return false; // b0rken + break; + } + + stream >> val; + mViewHeaderPolicy = (ViewHeaderPolicy)val; + switch(mViewHeaderPolicy) + { case ShowHeaderAlways: case NeverShowHeader: - // ok - break; + // ok + break; default: - kDebug() << "Invalid theme view header policy"; - return false; // b0rken - break; - } - - if ( themeVersion >= gThemeMinimumVersionWithIconSizeField ) - { - // icon size parameter - stream >> mIconSize; - if ( ( mIconSize < 8 ) || ( mIconSize > 64 ) ) - mIconSize = gThemeDefaultIconSize; // limit insane values - } else { - mIconSize = gThemeDefaultIconSize; - } + kDebug() << "Invalid theme view header policy"; + return false; // b0rken + break; + } + + if ( themeVersion >= gThemeMinimumVersionWithIconSizeField ) + { + // icon size parameter + stream >> mIconSize; + if ( ( mIconSize < 8 ) || ( mIconSize > 64 ) ) + mIconSize = gThemeDefaultIconSize; // limit insane values + } else { + mIconSize = gThemeDefaultIconSize; + } - // column count - stream >> val; - if ( val < 1 || val > 50 ) - return false; // plain b0rken ( negative, zero or more than 50 columns ) - - for ( int i = 0; i < val ; ++i ) - { - Column * col = new Column(); - if ( !col->load( stream, themeVersion ) ) - { - kDebug() << "Column loading failed"; - delete col; - return false; + // column count + stream >> val; + if ( val < 1 || val > 50 ) + return false; // plain b0rken ( negative, zero or more than 50 columns ) + + for ( int i = 0; i < val ; ++i ) + { + Column * col = new Column(); + if ( !col->load( stream, themeVersion ) ) + { + kDebug() << "Column loading failed"; + delete col; + return false; + } + addColumn( col ); } - addColumn( col ); - } - return true; + return true; } void Theme::save( QDataStream &stream ) const { - stream << (int)gThemeCurrentVersion; + stream << (int)gThemeCurrentVersion; + + stream << (int)mGroupHeaderBackgroundMode; + stream << mGroupHeaderBackgroundColor; + stream << (int)mGroupHeaderBackgroundStyle; + stream << (int)mViewHeaderPolicy; + stream << mIconSize; + + const int cnt = mColumns.count(); + stream << (int)cnt; - stream << (int)mGroupHeaderBackgroundMode; - stream << mGroupHeaderBackgroundColor; - stream << (int)mGroupHeaderBackgroundStyle; - stream << (int)mViewHeaderPolicy; - stream << mIconSize; - - const int cnt = mColumns.count(); - stream << (int)cnt; - - - for ( int i = 0; i < cnt ; ++i ) - { - Column * col = mColumns.at( i ); - col->save( stream ); - } + + for ( int i = 0; i < cnt ; ++i ) + { + Column * col = mColumns.at( i ); + col->save( stream ); + } } diff -Nru kdepim-4.12.97/messagelist/core/themedelegate.cpp kdepim-4.13.0/messagelist/core/themedelegate.cpp --- kdepim-4.12.97/messagelist/core/themedelegate.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/themedelegate.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -48,11 +48,11 @@ ThemeDelegate::ThemeDelegate( QAbstractItemView * parent ) - : QStyledItemDelegate( parent ) + : QStyledItemDelegate( parent ) { - mItemView = parent; - mTheme = 0; - connect( KGlobalSettings::self(), SIGNAL(kdisplayFontChanged()), this, SLOT(slotGeneralFontChanged()) ); + mItemView = parent; + mTheme = 0; + connect( KGlobalSettings::self(), SIGNAL(kdisplayFontChanged()), this, SLOT(slotGeneralFontChanged()) ); } ThemeDelegate::~ThemeDelegate() @@ -61,333 +61,333 @@ void ThemeDelegate::setTheme( const Theme * theme ) { - mTheme = theme; + mTheme = theme; - if ( !mTheme ) - return; // hum + if ( !mTheme ) + return; // hum - // Rebuild the group header background color cache - switch( mTheme->groupHeaderBackgroundMode() ) - { + // Rebuild the group header background color cache + switch( mTheme->groupHeaderBackgroundMode() ) + { case Theme::Transparent: - mGroupHeaderBackgroundColor = QColor(); // invalid - break; + mGroupHeaderBackgroundColor = QColor(); // invalid + break; case Theme::CustomColor: - mGroupHeaderBackgroundColor = mTheme->groupHeaderBackgroundColor(); - break; + mGroupHeaderBackgroundColor = mTheme->groupHeaderBackgroundColor(); + break; case Theme::AutoColor: { - QPalette pal = mItemView->palette(); - QColor txt = pal.color( QPalette::Normal, QPalette::Text ); - QColor bck = pal.color( QPalette::Normal, QPalette::Base ); - mGroupHeaderBackgroundColor = QColor( - ( txt.red() + ( bck.red() * 3 ) ) / 4, - ( txt.green() + ( bck.green() * 3 ) ) / 4, - ( txt.blue() + ( bck.blue() * 3 ) ) / 4 - ); - } - break; - } - mItemView->reset(); + QPalette pal = mItemView->palette(); + QColor txt = pal.color( QPalette::Normal, QPalette::Text ); + QColor bck = pal.color( QPalette::Normal, QPalette::Base ); + mGroupHeaderBackgroundColor = QColor( + ( txt.red() + ( bck.red() * 3 ) ) / 4, + ( txt.green() + ( bck.green() * 3 ) ) / 4, + ( txt.blue() + ( bck.blue() * 3 ) ) / 4 + ); + } + break; + } + mItemView->reset(); } static QFontMetrics cachedFontMetrics( const QFont &font ) { - static QHash fontMetricsCache; - const QString fontKey = font.key(); + static QHash fontMetricsCache; + const QString fontKey = font.key(); - if ( !fontMetricsCache.contains( fontKey ) ) { - QFontMetrics *metrics = new QFontMetrics( font ); - fontMetricsCache.insert( fontKey, metrics ); - } + if ( !fontMetricsCache.contains( fontKey ) ) { + QFontMetrics *metrics = new QFontMetrics( font ); + fontMetricsCache.insert( fontKey, metrics ); + } - return *fontMetricsCache[ fontKey ]; + return *fontMetricsCache[ fontKey ]; } static int cachedFontHeightKey( const QFont &font, const QString &fontKey ) { - static QHash fontHeightCache; + static QHash fontHeightCache; - if ( !fontHeightCache.contains( fontKey ) ) { - fontHeightCache.insert( fontKey, cachedFontMetrics( font ).height() ); - } + if ( !fontHeightCache.contains( fontKey ) ) { + fontHeightCache.insert( fontKey, cachedFontMetrics( font ).height() ); + } - return fontHeightCache[ fontKey ]; + return fontHeightCache[ fontKey ]; } static inline void paint_right_aligned_elided_text( const QString &text, Theme::ContentItem * ci, QPainter * painter, int &left, int top, int &right, Qt::LayoutDirection layoutDir, const QFont &font ) { - painter->setFont( font ); - const QFontMetrics fontMetrics = cachedFontMetrics( font ); - const int w = right - left; - const QString elidedText = fontMetrics.elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideLeft : Qt::ElideRight, w ); - const QRect rct( left, top, w, fontMetrics.height() ); - QRect outRct; + painter->setFont( font ); + const QFontMetrics fontMetrics = cachedFontMetrics( font ); + const int w = right - left; + const QString elidedText = fontMetrics.elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideLeft : Qt::ElideRight, w ); + const QRect rct( left, top, w, fontMetrics.height() ); + QRect outRct; - if ( ci->softenByBlending() ) - { - qreal oldOpacity = painter->opacity(); - painter->setOpacity( 0.6 ); - painter->drawText( rct, Qt::AlignTop | Qt::AlignRight | Qt::TextSingleLine, elidedText, &outRct ); - painter->setOpacity( oldOpacity ); - } else { - painter->drawText( rct, Qt::AlignTop | Qt::AlignRight | Qt::TextSingleLine, elidedText, &outRct ); - } - if ( layoutDir == Qt::LeftToRight ) - right -= outRct.width() + gHorizontalItemSpacing; - else - left += outRct.width() + gHorizontalItemSpacing; + if ( ci->softenByBlending() ) + { + qreal oldOpacity = painter->opacity(); + painter->setOpacity( 0.6 ); + painter->drawText( rct, Qt::AlignTop | Qt::AlignRight | Qt::TextSingleLine, elidedText, &outRct ); + painter->setOpacity( oldOpacity ); + } else { + painter->drawText( rct, Qt::AlignTop | Qt::AlignRight | Qt::TextSingleLine, elidedText, &outRct ); + } + if ( layoutDir == Qt::LeftToRight ) + right -= outRct.width() + gHorizontalItemSpacing; + else + left += outRct.width() + gHorizontalItemSpacing; } static inline void compute_bounding_rect_for_right_aligned_elided_text( const QString &text, int &left, int top, int &right, QRect &outRect, Qt::LayoutDirection layoutDir, const QFont &font ) { - const QFontMetrics fontMetrics = cachedFontMetrics( font ); - const int w = right - left; - const QString elidedText = fontMetrics.elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideLeft : Qt::ElideRight, w ); - const QRect rct( left, top, w, fontMetrics.height() ); - const Qt::AlignmentFlag af = layoutDir == Qt::LeftToRight ? Qt::AlignRight : Qt::AlignLeft; - outRect = fontMetrics.boundingRect( rct, Qt::AlignTop | af | Qt::TextSingleLine, elidedText ); - if ( layoutDir == Qt::LeftToRight ) - right -= outRect.width() + gHorizontalItemSpacing; - else - left += outRect.width() + gHorizontalItemSpacing; + const QFontMetrics fontMetrics = cachedFontMetrics( font ); + const int w = right - left; + const QString elidedText = fontMetrics.elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideLeft : Qt::ElideRight, w ); + const QRect rct( left, top, w, fontMetrics.height() ); + const Qt::AlignmentFlag af = layoutDir == Qt::LeftToRight ? Qt::AlignRight : Qt::AlignLeft; + outRect = fontMetrics.boundingRect( rct, Qt::AlignTop | af | Qt::TextSingleLine, elidedText ); + if ( layoutDir == Qt::LeftToRight ) + right -= outRect.width() + gHorizontalItemSpacing; + else + left += outRect.width() + gHorizontalItemSpacing; } static inline void paint_left_aligned_elided_text( const QString &text, Theme::ContentItem * ci, QPainter * painter, int &left, int top, int &right, Qt::LayoutDirection layoutDir, const QFont &font ) { - painter->setFont( font ); - const QFontMetrics fontMetrics = cachedFontMetrics( font ); - const int w = right - left; - const QString elidedText = fontMetrics.elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideRight : Qt::ElideLeft, w ); - const QRect rct( left, top, w, fontMetrics.height() ); - QRect outRct; - if ( ci->softenByBlending() ) - { - qreal oldOpacity = painter->opacity(); - painter->setOpacity( 0.6 ); - painter->drawText( rct, Qt::AlignTop | Qt::AlignLeft | Qt::TextSingleLine, elidedText, &outRct ); - painter->setOpacity( oldOpacity ); - } else { - painter->drawText( rct, Qt::AlignTop | Qt::AlignLeft | Qt::TextSingleLine, elidedText, &outRct ); - } - if ( layoutDir == Qt::LeftToRight ) - left += outRct.width() + gHorizontalItemSpacing; - else - right -= outRct.width() + gHorizontalItemSpacing; + painter->setFont( font ); + const QFontMetrics fontMetrics = cachedFontMetrics( font ); + const int w = right - left; + const QString elidedText = fontMetrics.elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideRight : Qt::ElideLeft, w ); + const QRect rct( left, top, w, fontMetrics.height() ); + QRect outRct; + if ( ci->softenByBlending() ) + { + qreal oldOpacity = painter->opacity(); + painter->setOpacity( 0.6 ); + painter->drawText( rct, Qt::AlignTop | Qt::AlignLeft | Qt::TextSingleLine, elidedText, &outRct ); + painter->setOpacity( oldOpacity ); + } else { + painter->drawText( rct, Qt::AlignTop | Qt::AlignLeft | Qt::TextSingleLine, elidedText, &outRct ); + } + if ( layoutDir == Qt::LeftToRight ) + left += outRct.width() + gHorizontalItemSpacing; + else + right -= outRct.width() + gHorizontalItemSpacing; } static inline void compute_bounding_rect_for_left_aligned_elided_text( const QString &text, int &left, int top, int &right, QRect &outRect, Qt::LayoutDirection layoutDir, const QFont &font ) { - const QFontMetrics fontMetrics = cachedFontMetrics( font ); - const int w = right - left; - const QString elidedText = fontMetrics.elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideRight : Qt::ElideLeft, w ); - const QRect rct( left, top, w, fontMetrics.height() ); - const Qt::AlignmentFlag af = layoutDir == Qt::LeftToRight ? Qt::AlignLeft : Qt::AlignRight; - outRect = fontMetrics.boundingRect( rct, Qt::AlignTop | af | Qt::TextSingleLine, elidedText ); - if ( layoutDir == Qt::LeftToRight ) - left += outRect.width() + gHorizontalItemSpacing; - else - right -= outRect.width() + gHorizontalItemSpacing; + const QFontMetrics fontMetrics = cachedFontMetrics( font ); + const int w = right - left; + const QString elidedText = fontMetrics.elidedText( text, layoutDir == Qt::LeftToRight ? Qt::ElideRight : Qt::ElideLeft, w ); + const QRect rct( left, top, w, fontMetrics.height() ); + const Qt::AlignmentFlag af = layoutDir == Qt::LeftToRight ? Qt::AlignLeft : Qt::AlignRight; + outRect = fontMetrics.boundingRect( rct, Qt::AlignTop | af | Qt::TextSingleLine, elidedText ); + if ( layoutDir == Qt::LeftToRight ) + left += outRect.width() + gHorizontalItemSpacing; + else + right -= outRect.width() + gHorizontalItemSpacing; } static inline const QPixmap * get_read_state_icon( Item * item ) { - if ( item->status().isQueued() ) - return Manager::instance()->pixmapMessageQueued(); - else if ( item->status().isSent() ) - return Manager::instance()->pixmapMessageSent(); - else if ( item->status().isRead() ) - return Manager::instance()->pixmapMessageRead(); - else if ( !item->status().isRead() ) - return Manager::instance()->pixmapMessageUnread(); - else if ( item->status().isDeleted() ) - return Manager::instance()->pixmapMessageDeleted(); + if ( item->status().isQueued() ) + return Manager::instance()->pixmapMessageQueued(); + else if ( item->status().isSent() ) + return Manager::instance()->pixmapMessageSent(); + else if ( item->status().isRead() ) + return Manager::instance()->pixmapMessageRead(); + else if ( !item->status().isRead() ) + return Manager::instance()->pixmapMessageUnread(); + else if ( item->status().isDeleted() ) + return Manager::instance()->pixmapMessageDeleted(); - // Uhm... should never happen.. but fallback to "read"... - return Manager::instance()->pixmapMessageRead(); + // Uhm... should never happen.. but fallback to "read"... + return Manager::instance()->pixmapMessageRead(); } static inline const QPixmap * get_combined_read_replied_state_icon( MessageItem * messageItem ) { - if ( messageItem->status().isReplied() ) - { + if ( messageItem->status().isReplied() ) + { + if ( messageItem->status().isForwarded() ) + return Manager::instance()->pixmapMessageRepliedAndForwarded(); + return Manager::instance()->pixmapMessageReplied(); + } if ( messageItem->status().isForwarded() ) - return Manager::instance()->pixmapMessageRepliedAndForwarded(); - return Manager::instance()->pixmapMessageReplied(); - } - if ( messageItem->status().isForwarded() ) - return Manager::instance()->pixmapMessageForwarded(); + return Manager::instance()->pixmapMessageForwarded(); - return get_read_state_icon( messageItem ); + return get_read_state_icon( messageItem ); } static inline const QPixmap * get_encryption_state_icon( MessageItem * messageItem, bool *treatAsEnabled ) { - switch( messageItem->encryptionState() ) - { + switch( messageItem->encryptionState() ) + { case MessageItem::FullyEncrypted: - *treatAsEnabled = true; - return Manager::instance()->pixmapMessageFullyEncrypted(); - break; + *treatAsEnabled = true; + return Manager::instance()->pixmapMessageFullyEncrypted(); + break; case MessageItem::PartiallyEncrypted: - *treatAsEnabled = true; - return Manager::instance()->pixmapMessagePartiallyEncrypted(); - break; + *treatAsEnabled = true; + return Manager::instance()->pixmapMessagePartiallyEncrypted(); + break; case MessageItem::EncryptionStateUnknown: - *treatAsEnabled = false; - return Manager::instance()->pixmapMessageUndefinedEncrypted(); - break; + *treatAsEnabled = false; + return Manager::instance()->pixmapMessageUndefinedEncrypted(); + break; case MessageItem::NotEncrypted: - *treatAsEnabled = false; - return Manager::instance()->pixmapMessageNotEncrypted(); - break; + *treatAsEnabled = false; + return Manager::instance()->pixmapMessageNotEncrypted(); + break; default: - // should never happen - Q_ASSERT( false ); - break; - } + // should never happen + Q_ASSERT( false ); + break; + } - *treatAsEnabled = false; - return Manager::instance()->pixmapMessageUndefinedEncrypted(); + *treatAsEnabled = false; + return Manager::instance()->pixmapMessageUndefinedEncrypted(); } static inline const QPixmap * get_signature_state_icon( MessageItem * messageItem, bool *treatAsEnabled ) { - switch( messageItem->signatureState() ) - { + switch( messageItem->signatureState() ) + { case MessageItem::FullySigned: - *treatAsEnabled = true; - return Manager::instance()->pixmapMessageFullySigned(); - break; + *treatAsEnabled = true; + return Manager::instance()->pixmapMessageFullySigned(); + break; case MessageItem::PartiallySigned: - *treatAsEnabled = true; - return Manager::instance()->pixmapMessagePartiallySigned(); - break; + *treatAsEnabled = true; + return Manager::instance()->pixmapMessagePartiallySigned(); + break; case MessageItem::SignatureStateUnknown: - *treatAsEnabled = false; - return Manager::instance()->pixmapMessageUndefinedSigned(); - break; + *treatAsEnabled = false; + return Manager::instance()->pixmapMessageUndefinedSigned(); + break; case MessageItem::NotSigned: - *treatAsEnabled = false; - return Manager::instance()->pixmapMessageNotSigned(); - break; + *treatAsEnabled = false; + return Manager::instance()->pixmapMessageNotSigned(); + break; default: - // should never happen - Q_ASSERT( false ); - break; - } + // should never happen + Q_ASSERT( false ); + break; + } - *treatAsEnabled = false; - return Manager::instance()->pixmapMessageUndefinedSigned(); + *treatAsEnabled = false; + return Manager::instance()->pixmapMessageUndefinedSigned(); } static inline const QPixmap * get_replied_state_icon( MessageItem * messageItem ) { - if ( messageItem->status().isReplied() ) - { + if ( messageItem->status().isReplied() ) + { + if ( messageItem->status().isForwarded() ) + return Manager::instance()->pixmapMessageRepliedAndForwarded(); + return Manager::instance()->pixmapMessageReplied(); + } if ( messageItem->status().isForwarded() ) - return Manager::instance()->pixmapMessageRepliedAndForwarded(); - return Manager::instance()->pixmapMessageReplied(); - } - if ( messageItem->status().isForwarded() ) - return Manager::instance()->pixmapMessageForwarded(); + return Manager::instance()->pixmapMessageForwarded(); - return 0; + return 0; } static inline const QPixmap * get_spam_ham_state_icon( MessageItem * messageItem ) { - if ( messageItem->status().isSpam() ) - return Manager::instance()->pixmapMessageSpam(); - if ( messageItem->status().isHam() ) - return Manager::instance()->pixmapMessageHam(); - return 0; + if ( messageItem->status().isSpam() ) + return Manager::instance()->pixmapMessageSpam(); + if ( messageItem->status().isHam() ) + return Manager::instance()->pixmapMessageHam(); + return 0; } static inline const QPixmap * get_watched_ignored_state_icon( MessageItem * messageItem ) { - if ( messageItem->status().isIgnored() ) - return Manager::instance()->pixmapMessageIgnored(); - if ( messageItem->status().isWatched() ) - return Manager::instance()->pixmapMessageWatched(); - return 0; + if ( messageItem->status().isIgnored() ) + return Manager::instance()->pixmapMessageIgnored(); + if ( messageItem->status().isWatched() ) + return Manager::instance()->pixmapMessageWatched(); + return 0; } static inline void paint_vertical_line( QPainter * painter, int &left, int top, int &right, int bottom, bool alignOnRight ) { - if ( alignOnRight ) - { - right -= 1; - if ( right < 0 ) - return; - painter->drawLine( right, top, right, bottom ); - right -= 2; - right -= gHorizontalItemSpacing; - } else { - left += 1; - if ( left > right ) - return; - painter->drawLine( left, top, left, bottom ); - left += 2 + gHorizontalItemSpacing; - } + if ( alignOnRight ) + { + right -= 1; + if ( right < 0 ) + return; + painter->drawLine( right, top, right, bottom ); + right -= 2; + right -= gHorizontalItemSpacing; + } else { + left += 1; + if ( left > right ) + return; + painter->drawLine( left, top, left, bottom ); + left += 2 + gHorizontalItemSpacing; + } } static inline void compute_bounding_rect_for_vertical_line( int &left, int top, int &right, int bottom, QRect &outRect, bool alignOnRight ) { - if ( alignOnRight ) - { - right -= 3; - outRect = QRect( right, top, 3, bottom - top ); - right -= gHorizontalItemSpacing; - } else { - outRect = QRect( left, top, 3, bottom - top ); - left += 3 + gHorizontalItemSpacing; - } + if ( alignOnRight ) + { + right -= 3; + outRect = QRect( right, top, 3, bottom - top ); + right -= gHorizontalItemSpacing; + } else { + outRect = QRect( left, top, 3, bottom - top ); + left += 3 + gHorizontalItemSpacing; + } } static inline void paint_horizontal_spacer( int &left, int, int &right, int, bool alignOnRight ) { - if ( alignOnRight ) - { - right -= 3 + gHorizontalItemSpacing; - } else { - left += 3 + gHorizontalItemSpacing; - } + if ( alignOnRight ) + { + right -= 3 + gHorizontalItemSpacing; + } else { + left += 3 + gHorizontalItemSpacing; + } } static inline void compute_bounding_rect_for_horizontal_spacer( int &left, int top, int &right, int bottom, QRect &outRect, bool alignOnRight ) { - if ( alignOnRight ) - { - right -= 3; - outRect = QRect( right, top, 3, bottom - top ); - right -= gHorizontalItemSpacing; - } else { - outRect = QRect( left, top, 3, bottom - top ); - left += 3 + gHorizontalItemSpacing; - } + if ( alignOnRight ) + { + right -= 3; + outRect = QRect( right, top, 3, bottom - top ); + right -= gHorizontalItemSpacing; + } else { + outRect = QRect( left, top, 3, bottom - top ); + left += 3 + gHorizontalItemSpacing; + } } static inline void paint_permanent_icon( const QPixmap * pix, Theme::ContentItem *, QPainter * painter, int &left, int top, int &right, bool alignOnRight, int iconSize ) { - if ( alignOnRight ) - { - right -= iconSize; // this icon is always present - if ( right < 0 ) - return; - painter->drawPixmap( right, top, iconSize, iconSize, *pix ); - right -= gHorizontalItemSpacing; - } else { - if ( left > ( right - iconSize ) ) - return; - painter->drawPixmap( left, top, iconSize, iconSize, *pix ); - left += iconSize + gHorizontalItemSpacing; - } + if ( alignOnRight ) + { + right -= iconSize; // this icon is always present + if ( right < 0 ) + return; + painter->drawPixmap( right, top, iconSize, iconSize, *pix ); + right -= gHorizontalItemSpacing; + } else { + if ( left > ( right - iconSize ) ) + return; + painter->drawPixmap( left, top, iconSize, iconSize, *pix ); + left += iconSize + gHorizontalItemSpacing; + } } static inline void compute_bounding_rect_for_permanent_icon( Theme::ContentItem *, int &left, @@ -395,15 +395,15 @@ QRect &outRect, bool alignOnRight, int iconSize ) { - if ( alignOnRight ) - { - right -= iconSize; // this icon is always present - outRect = QRect( right, top, iconSize, iconSize ); - right -= gHorizontalItemSpacing; - } else { - outRect = QRect( left, top, iconSize, iconSize ); - left += iconSize + gHorizontalItemSpacing; - } + if ( alignOnRight ) + { + right -= iconSize; // this icon is always present + outRect = QRect( right, top, iconSize, iconSize ); + right -= gHorizontalItemSpacing; + } else { + outRect = QRect( left, top, iconSize, iconSize ); + left += iconSize + gHorizontalItemSpacing; + } } @@ -412,31 +412,31 @@ int top, int &right, bool alignOnRight, int iconSize ) { - if ( enabled ) - { - paint_permanent_icon( pix, ci, painter, left, top, right, alignOnRight, iconSize ); - return; - } - - // off -> icon disabled - if ( ci->hideWhenDisabled() ) - return; // doesn't even take space - - if ( ci->softenByBlendingWhenDisabled() ) - { - // still paint, but very soft - qreal oldOpacity = painter->opacity(); - painter->setOpacity( 0.1 ); - paint_permanent_icon( pix, ci, painter, left, top, right, alignOnRight, iconSize ); - painter->setOpacity( oldOpacity ); - return; - } + if ( enabled ) + { + paint_permanent_icon( pix, ci, painter, left, top, right, alignOnRight, iconSize ); + return; + } + + // off -> icon disabled + if ( ci->hideWhenDisabled() ) + return; // doesn't even take space + + if ( ci->softenByBlendingWhenDisabled() ) + { + // still paint, but very soft + qreal oldOpacity = painter->opacity(); + painter->setOpacity( 0.1 ); + paint_permanent_icon( pix, ci, painter, left, top, right, alignOnRight, iconSize ); + painter->setOpacity( oldOpacity ); + return; + } - // just takes space - if ( alignOnRight ) - right -= iconSize + gHorizontalItemSpacing; - else - left += iconSize + gHorizontalItemSpacing; + // just takes space + if ( alignOnRight ) + right -= iconSize + gHorizontalItemSpacing; + else + left += iconSize + gHorizontalItemSpacing; } static inline void compute_bounding_rect_for_boolean_state_icon( bool enabled, Theme::ContentItem * ci, @@ -444,1230 +444,1230 @@ QRect &outRect, bool alignOnRight, int iconSize ) { - if ( ( !enabled ) && ci->hideWhenDisabled() ) - { - outRect = QRect(); - return; // doesn't even take space - } + if ( ( !enabled ) && ci->hideWhenDisabled() ) + { + outRect = QRect(); + return; // doesn't even take space + } - compute_bounding_rect_for_permanent_icon( ci, left, top, right, outRect, alignOnRight, iconSize ); + compute_bounding_rect_for_permanent_icon( ci, left, top, right, outRect, alignOnRight, iconSize ); } static inline void paint_tag_list( const QList< MessageItem::Tag * > &tagList, QPainter * painter, int &left, int top, int &right, bool alignOnRight, int iconSize ) { - if ( alignOnRight ) - { - foreach( const MessageItem::Tag *tag, tagList ) { - right -= iconSize; // this icon is always present - if ( right < 0 ) - return; - painter->drawPixmap( right, top, iconSize, iconSize, tag->pixmap() ); - right -= gHorizontalItemSpacing; - } - } else { - foreach( const MessageItem::Tag *tag, tagList ) { - if ( left > right - iconSize ) - return; - painter->drawPixmap( left, top, iconSize, iconSize, tag->pixmap() ); - left += iconSize + gHorizontalItemSpacing; + if ( alignOnRight ) + { + foreach( const MessageItem::Tag *tag, tagList ) { + right -= iconSize; // this icon is always present + if ( right < 0 ) + return; + painter->drawPixmap( right, top, iconSize, iconSize, tag->pixmap() ); + right -= gHorizontalItemSpacing; + } + } else { + foreach( const MessageItem::Tag *tag, tagList ) { + if ( left > right - iconSize ) + return; + painter->drawPixmap( left, top, iconSize, iconSize, tag->pixmap() ); + left += iconSize + gHorizontalItemSpacing; + } } - } } static inline void compute_bounding_rect_for_tag_list( const QList< MessageItem::Tag * > &tagList, int &left, int top, int &right, QRect &outRect, bool alignOnRight, int iconSize ) { - int width = tagList.count() * ( iconSize + gHorizontalItemSpacing ); - if ( alignOnRight ) - { - right -= width; - outRect = QRect( right, top, width, iconSize ); - } else { - outRect = QRect( left, top, width, iconSize ); - left += width; - } + int width = tagList.count() * ( iconSize + gHorizontalItemSpacing ); + if ( alignOnRight ) + { + right -= width; + outRect = QRect( right, top, width, iconSize ); + } else { + outRect = QRect( left, top, width, iconSize ); + left += width; + } } static inline void compute_size_hint_for_item( Theme::ContentItem * ci, int &maxh, int &totalw, int iconSize, const Item *item ) { - if ( ci->displaysText() ) - { - const QFont font = ThemeDelegate::itemFont( ci, item ); - const QString fontKey = ThemeDelegate::itemFontKey( ci, item ); - const int fontHeight = cachedFontHeightKey( font, fontKey ); - if ( fontHeight > maxh ) - maxh = fontHeight; - totalw += ci->displaysLongText() ? 128 : 64; - return; - } - - if ( ci->isIcon() ) - { - totalw += iconSize + gHorizontalItemSpacing; - if ( maxh < iconSize ) - maxh = iconSize; - return; - } + if ( ci->displaysText() ) + { + const QFont font = ThemeDelegate::itemFont( ci, item ); + const QString fontKey = ThemeDelegate::itemFontKey( ci, item ); + const int fontHeight = cachedFontHeightKey( font, fontKey ); + if ( fontHeight > maxh ) + maxh = fontHeight; + totalw += ci->displaysLongText() ? 128 : 64; + return; + } + + if ( ci->isIcon() ) + { + totalw += iconSize + gHorizontalItemSpacing; + if ( maxh < iconSize ) + maxh = iconSize; + return; + } + + if ( ci->isSpacer() ) + { + if ( 18 > maxh ) + maxh = 18; + totalw += 3 + gHorizontalItemSpacing; + return; + } - if ( ci->isSpacer() ) - { + // should never be reached if ( 18 > maxh ) - maxh = 18; - totalw += 3 + gHorizontalItemSpacing; - return; - } - - // should never be reached - if ( 18 > maxh ) - maxh = 18; - totalw += gHorizontalItemSpacing; + maxh = 18; + totalw += gHorizontalItemSpacing; } static inline QSize compute_size_hint_for_row( const Theme::Row * r, int iconSize, const Item *item ) { - int maxh = 8; // at least 8 pixels for a pixmap - int totalw = 0; + int maxh = 8; // at least 8 pixels for a pixmap + int totalw = 0; - // right aligned stuff first - const QList< Theme::ContentItem * > * items = &( r->rightItems() ); - QList< Theme::ContentItem * >::ConstIterator itemit, endItemIt; + // right aligned stuff first + const QList< Theme::ContentItem * > * items = &( r->rightItems() ); + QList< Theme::ContentItem * >::ConstIterator itemit, endItemIt; - for ( itemit = items->begin(), endItemIt = items->end(); itemit != endItemIt; ++itemit ) - compute_size_hint_for_item( const_cast< Theme::ContentItem * >( *itemit ), maxh, totalw, iconSize, item ); + for ( itemit = items->begin(), endItemIt = items->end(); itemit != endItemIt; ++itemit ) + compute_size_hint_for_item( const_cast< Theme::ContentItem * >( *itemit ), maxh, totalw, iconSize, item ); - // then left aligned stuff - items = &( r->leftItems() ); + // then left aligned stuff + items = &( r->leftItems() ); - for ( itemit = items->begin(), endItemIt = items->end(); itemit != endItemIt; ++itemit ) - compute_size_hint_for_item( const_cast< Theme::ContentItem * >( *itemit ), maxh, totalw, iconSize, item ); + for ( itemit = items->begin(), endItemIt = items->end(); itemit != endItemIt; ++itemit ) + compute_size_hint_for_item( const_cast< Theme::ContentItem * >( *itemit ), maxh, totalw, iconSize, item ); - return QSize( totalw, maxh ); + return QSize( totalw, maxh ); } void ThemeDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { - if ( !index.isValid() ) - return; // bleah - - Item * item = itemFromIndex( index ); - if ( !item ) - return; // hm... - - QStyleOptionViewItemV4 opt = option; - initStyleOption( &opt, index ); + if ( !index.isValid() ) + return; // bleah - opt.text.clear(); // draw no text for me, please.. I'll do it in a while - - // Set background color of control if necessary - if ( item->type() == Item::Message ) { - MessageItem * msgItem = static_cast< MessageItem * >( item ); - if ( msgItem->backgroundColor().isValid() ) - opt.backgroundBrush = QBrush( msgItem->backgroundColor() ); - } + Item * item = itemFromIndex( index ); + if ( !item ) + return; // hm... + + QStyleOptionViewItemV4 opt = option; + initStyleOption( &opt, index ); + + opt.text.clear(); // draw no text for me, please.. I'll do it in a while + + // Set background color of control if necessary + if ( item->type() == Item::Message ) { + MessageItem * msgItem = static_cast< MessageItem * >( item ); + if ( msgItem->backgroundColor().isValid() ) + opt.backgroundBrush = QBrush( msgItem->backgroundColor() ); + } - QStyle * style = mItemView->style(); - style->drawControl( QStyle::CE_ItemViewItem, &opt, painter, mItemView ); + QStyle * style = mItemView->style(); + style->drawControl( QStyle::CE_ItemViewItem, &opt, painter, mItemView ); - if ( !mTheme ) - return; // hm hm... + if ( !mTheme ) + return; // hm hm... - const Theme::Column * skcolumn = mTheme->column( index.column() ); - if ( !skcolumn ) - return; // bleah + const Theme::Column * skcolumn = mTheme->column( index.column() ); + if ( !skcolumn ) + return; // bleah - const QList< Theme::Row * > * rows; // I'd like to have it as reference, but gcc complains... + const QList< Theme::Row * > * rows; // I'd like to have it as reference, but gcc complains... - MessageItem * messageItem = 0; - GroupHeaderItem * groupHeaderItem = 0; + MessageItem * messageItem = 0; + GroupHeaderItem * groupHeaderItem = 0; - int top = opt.rect.top(); - int right = opt.rect.left() + opt.rect.width(); // don't use opt.rect.right() since it's screwed - int left = opt.rect.left(); + int top = opt.rect.top(); + int right = opt.rect.left() + opt.rect.width(); // don't use opt.rect.right() since it's screwed + int left = opt.rect.left(); - // Storing the changed members one by one is faster than saving the painter state - QFont oldFont = painter->font(); - QPen oldPen = painter->pen(); - qreal oldOpacity = painter->opacity(); + // Storing the changed members one by one is faster than saving the painter state + QFont oldFont = painter->font(); + QPen oldPen = painter->pen(); + qreal oldOpacity = painter->opacity(); - QPen defaultPen; - bool usingNonDefaultTextColor = false; + QPen defaultPen; + bool usingNonDefaultTextColor = false; - switch ( item->type() ) - { + switch ( item->type() ) + { case Item::Message: { - rows = &( skcolumn->messageRows() ); - messageItem = static_cast< MessageItem * >( item ); + rows = &( skcolumn->messageRows() ); + messageItem = static_cast< MessageItem * >( item ); - if ( - ( ! ( opt.state & QStyle::State_Enabled ) ) || - messageItem->aboutToBeRemoved() || - ( ! messageItem->isValid() ) - ) - { - painter->setOpacity( 0.5 ); - defaultPen = QPen( opt.palette.brush( QPalette::Disabled, QPalette::Text ), 0 ); - } else { - - QPalette::ColorGroup cg; - - if ( opt.state & QStyle::State_Active ) - cg = QPalette::Normal; - else - cg = QPalette::Inactive; - - if ( opt.state & QStyle::State_Selected ) + if ( + ( ! ( opt.state & QStyle::State_Enabled ) ) || + messageItem->aboutToBeRemoved() || + ( ! messageItem->isValid() ) + ) { - defaultPen = QPen( opt.palette.brush( cg, QPalette::HighlightedText ), 0 ); + painter->setOpacity( 0.5 ); + defaultPen = QPen( opt.palette.brush( QPalette::Disabled, QPalette::Text ), 0 ); } else { - if ( messageItem->textColor().isValid() ) - { - usingNonDefaultTextColor = true; - defaultPen = QPen( messageItem->textColor(), 0 ); - } else { - defaultPen = QPen( opt.palette.brush( cg, QPalette::Text ), 0 ); - } + + QPalette::ColorGroup cg; + + if ( opt.state & QStyle::State_Active ) + cg = QPalette::Normal; + else + cg = QPalette::Inactive; + + if ( opt.state & QStyle::State_Selected ) + { + defaultPen = QPen( opt.palette.brush( cg, QPalette::HighlightedText ), 0 ); + } else { + if ( messageItem->textColor().isValid() ) + { + usingNonDefaultTextColor = true; + defaultPen = QPen( messageItem->textColor(), 0 ); + } else { + defaultPen = QPen( opt.palette.brush( cg, QPalette::Text ), 0 ); + } + } } - } - top += gMessageVerticalMargin; - right -= gMessageHorizontalMargin; - left += gMessageHorizontalMargin; + top += gMessageVerticalMargin; + right -= gMessageHorizontalMargin; + left += gMessageHorizontalMargin; } - break; + break; case Item::GroupHeader: { - rows = &( skcolumn->groupHeaderRows() ); - groupHeaderItem = static_cast< GroupHeaderItem * >( item ); + rows = &( skcolumn->groupHeaderRows() ); + groupHeaderItem = static_cast< GroupHeaderItem * >( item ); - QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; + QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; - if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active)) - cg = QPalette::Inactive; + if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active)) + cg = QPalette::Inactive; - QPalette::ColorRole cr; + QPalette::ColorRole cr; - top += gGroupHeaderOuterVerticalMargin; - right -= gGroupHeaderOuterHorizontalMargin; - left += gGroupHeaderOuterHorizontalMargin; + top += gGroupHeaderOuterVerticalMargin; + right -= gGroupHeaderOuterHorizontalMargin; + left += gGroupHeaderOuterHorizontalMargin; - switch ( mTheme->groupHeaderBackgroundMode() ) - { + switch ( mTheme->groupHeaderBackgroundMode() ) + { case Theme::Transparent: - cr = ( opt.state & QStyle::State_Selected ) ? QPalette::HighlightedText : QPalette::Text; - defaultPen = QPen( opt.palette.brush( cg, cr ), 0 ); - break; + cr = ( opt.state & QStyle::State_Selected ) ? QPalette::HighlightedText : QPalette::Text; + defaultPen = QPen( opt.palette.brush( cg, cr ), 0 ); + break; case Theme::AutoColor: case Theme::CustomColor: - switch ( mTheme->groupHeaderBackgroundStyle() ) - { + switch ( mTheme->groupHeaderBackgroundStyle() ) + { case Theme::PlainRect: { - painter->fillRect( - QRect( left, top, right - left, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), - QBrush( mGroupHeaderBackgroundColor ) - ); + painter->fillRect( + QRect( left, top, right - left, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), + QBrush( mGroupHeaderBackgroundColor ) + ); } - break; + break; case Theme::PlainJoinedRect: { - int rleft = ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? left : opt.rect.left(); - int rright = ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? right : opt.rect.left() + opt.rect.width(); - painter->fillRect( - QRect( rleft, top, rright - rleft, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), - QBrush( mGroupHeaderBackgroundColor ) - ); + int rleft = ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? left : opt.rect.left(); + int rright = ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? right : opt.rect.left() + opt.rect.width(); + painter->fillRect( + QRect( rleft, top, rright - rleft, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), + QBrush( mGroupHeaderBackgroundColor ) + ); } - break; + break; case Theme::RoundedJoinedRect: { - if ( opt.viewItemPosition == QStyleOptionViewItemV4::Middle ) - { - painter->fillRect( - QRect( opt.rect.left(), top, opt.rect.width(), opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), - QBrush( mGroupHeaderBackgroundColor ) - ); - break; // don't fall through - } - if ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) - { - painter->fillRect( - QRect( opt.rect.left() + opt.rect.width() - 10, top, 10, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), - QBrush( mGroupHeaderBackgroundColor ) - ); - } else if ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) - { - painter->fillRect( - QRect( opt.rect.left(), top, 10 , opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), - QBrush( mGroupHeaderBackgroundColor ) - ); - } - // fall through anyway + if ( opt.viewItemPosition == QStyleOptionViewItemV4::Middle ) + { + painter->fillRect( + QRect( opt.rect.left(), top, opt.rect.width(), opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), + QBrush( mGroupHeaderBackgroundColor ) + ); + break; // don't fall through + } + if ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) + { + painter->fillRect( + QRect( opt.rect.left() + opt.rect.width() - 10, top, 10, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), + QBrush( mGroupHeaderBackgroundColor ) + ); + } else if ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) + { + painter->fillRect( + QRect( opt.rect.left(), top, 10 , opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), + QBrush( mGroupHeaderBackgroundColor ) + ); + } + // fall through anyway } case Theme::RoundedRect: { - painter->setPen( Qt::NoPen ); - bool hadAntialiasing = painter->renderHints() & QPainter::Antialiasing; - if ( !hadAntialiasing ) - painter->setRenderHint( QPainter::Antialiasing, true ); - painter->setBrush( QBrush( mGroupHeaderBackgroundColor ) ); - painter->setBackgroundMode( Qt::OpaqueMode ); - int w = right - left; - if ( w > 0 ) - painter->drawRoundedRect( - QRect( left, top, w, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), - 4.0, 4.0 - ); - if ( !hadAntialiasing ) - painter->setRenderHint( QPainter::Antialiasing, false ); - painter->setBackgroundMode( Qt::TransparentMode ); + painter->setPen( Qt::NoPen ); + bool hadAntialiasing = painter->renderHints() & QPainter::Antialiasing; + if ( !hadAntialiasing ) + painter->setRenderHint( QPainter::Antialiasing, true ); + painter->setBrush( QBrush( mGroupHeaderBackgroundColor ) ); + painter->setBackgroundMode( Qt::OpaqueMode ); + int w = right - left; + if ( w > 0 ) + painter->drawRoundedRect( + QRect( left, top, w, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), + 4.0, 4.0 + ); + if ( !hadAntialiasing ) + painter->setRenderHint( QPainter::Antialiasing, false ); + painter->setBackgroundMode( Qt::TransparentMode ); } - break; + break; case Theme::GradientJoinedRect: { - // FIXME: Could cache this brush - QLinearGradient gradient( 0, top, 0, top + opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); - gradient.setColorAt( 0.0, KColorScheme::shade( mGroupHeaderBackgroundColor, KColorScheme::LightShade, 0.3 ) ); - gradient.setColorAt( 1.0, mGroupHeaderBackgroundColor ); - if ( opt.viewItemPosition == QStyleOptionViewItemV4::Middle ) - { - painter->fillRect( - QRect( opt.rect.left(), top, opt.rect.width(), opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), - QBrush( gradient ) - ); - break; // don't fall through - } - if ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) - { - painter->fillRect( - QRect( opt.rect.left() + opt.rect.width() - 10, top, 10, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), - QBrush( gradient ) - ); - } else if ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) - { - painter->fillRect( - QRect( opt.rect.left(), top, 10 , opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), - QBrush( gradient ) - ); - } - // fall through anyway + // FIXME: Could cache this brush + QLinearGradient gradient( 0, top, 0, top + opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); + gradient.setColorAt( 0.0, KColorScheme::shade( mGroupHeaderBackgroundColor, KColorScheme::LightShade, 0.3 ) ); + gradient.setColorAt( 1.0, mGroupHeaderBackgroundColor ); + if ( opt.viewItemPosition == QStyleOptionViewItemV4::Middle ) + { + painter->fillRect( + QRect( opt.rect.left(), top, opt.rect.width(), opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), + QBrush( gradient ) + ); + break; // don't fall through + } + if ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) + { + painter->fillRect( + QRect( opt.rect.left() + opt.rect.width() - 10, top, 10, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), + QBrush( gradient ) + ); + } else if ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) + { + painter->fillRect( + QRect( opt.rect.left(), top, 10 , opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), + QBrush( gradient ) + ); + } + // fall through anyway } case Theme::GradientRect: { - // FIXME: Could cache this brush - QLinearGradient gradient( 0, top, 0, top + opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); - gradient.setColorAt( 0.0, KColorScheme::shade( mGroupHeaderBackgroundColor, KColorScheme::LightShade, 0.3 ) ); - gradient.setColorAt( 1.0, mGroupHeaderBackgroundColor ); - painter->setPen( Qt::NoPen ); - bool hadAntialiasing = painter->renderHints() & QPainter::Antialiasing; - if ( !hadAntialiasing ) - painter->setRenderHint( QPainter::Antialiasing, true ); - painter->setBrush( QBrush( gradient ) ); - painter->setBackgroundMode( Qt::OpaqueMode ); - int w = right - left; - if ( w > 0 ) - painter->drawRoundedRect( - QRect( left, top, w, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), - 4.0, 4.0 - ); - if ( !hadAntialiasing ) - painter->setRenderHint( QPainter::Antialiasing, false ); - painter->setBackgroundMode( Qt::TransparentMode ); + // FIXME: Could cache this brush + QLinearGradient gradient( 0, top, 0, top + opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); + gradient.setColorAt( 0.0, KColorScheme::shade( mGroupHeaderBackgroundColor, KColorScheme::LightShade, 0.3 ) ); + gradient.setColorAt( 1.0, mGroupHeaderBackgroundColor ); + painter->setPen( Qt::NoPen ); + bool hadAntialiasing = painter->renderHints() & QPainter::Antialiasing; + if ( !hadAntialiasing ) + painter->setRenderHint( QPainter::Antialiasing, true ); + painter->setBrush( QBrush( gradient ) ); + painter->setBackgroundMode( Qt::OpaqueMode ); + int w = right - left; + if ( w > 0 ) + painter->drawRoundedRect( + QRect( left, top, w, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ), + 4.0, 4.0 + ); + if ( !hadAntialiasing ) + painter->setRenderHint( QPainter::Antialiasing, false ); + painter->setBackgroundMode( Qt::TransparentMode ); } - break; + break; case Theme::StyledRect: { - // oxygen, for instance, has a nice graphics for selected items - opt.rect = QRect( left, top, right - left, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); - opt.state |= QStyle::State_Selected; - opt.viewItemPosition = QStyleOptionViewItemV4::OnlyOne; - opt.palette.setColor( cg ,QPalette::Highlight, mGroupHeaderBackgroundColor ); - style->drawControl( QStyle::CE_ItemViewItem, &opt, painter, mItemView ); + // oxygen, for instance, has a nice graphics for selected items + opt.rect = QRect( left, top, right - left, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); + opt.state |= QStyle::State_Selected; + opt.viewItemPosition = QStyleOptionViewItemV4::OnlyOne; + opt.palette.setColor( cg ,QPalette::Highlight, mGroupHeaderBackgroundColor ); + style->drawControl( QStyle::CE_ItemViewItem, &opt, painter, mItemView ); } - break; + break; case Theme::StyledJoinedRect: { - int rleft = ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? left : opt.rect.left(); - int rright = ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? right : opt.rect.left() + opt.rect.width(); - opt.rect = QRect( rleft, top, rright - rleft, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); - opt.state |= QStyle::State_Selected; - opt.palette.setColor( cg ,QPalette::Highlight, mGroupHeaderBackgroundColor ); - style->drawControl( QStyle::CE_ItemViewItem, &opt, painter, mItemView ); + int rleft = ( opt.viewItemPosition == QStyleOptionViewItemV4::Beginning ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? left : opt.rect.left(); + int rright = ( opt.viewItemPosition == QStyleOptionViewItemV4::End ) || ( opt.viewItemPosition == QStyleOptionViewItemV4::OnlyOne ) ? right : opt.rect.left() + opt.rect.width(); + opt.rect = QRect( rleft, top, rright - rleft, opt.rect.height() - ( gGroupHeaderInnerVerticalMargin * 2 ) ); + opt.state |= QStyle::State_Selected; + opt.palette.setColor( cg ,QPalette::Highlight, mGroupHeaderBackgroundColor ); + style->drawControl( QStyle::CE_ItemViewItem, &opt, painter, mItemView ); + } + break; } - break; - } - defaultPen = QPen( opt.palette.brush( cg, QPalette::Text ), 0 ); - break; - } - top += gGroupHeaderInnerVerticalMargin; - right -= gGroupHeaderInnerHorizontalMargin; - left += gGroupHeaderInnerHorizontalMargin; + defaultPen = QPen( opt.palette.brush( cg, QPalette::Text ), 0 ); + break; + } + top += gGroupHeaderInnerVerticalMargin; + right -= gGroupHeaderInnerHorizontalMargin; + left += gGroupHeaderInnerHorizontalMargin; } - break; + break; default: - Q_ASSERT( false ); - return; // bug - break; - } - - Qt::LayoutDirection layoutDir = mItemView->layoutDirection(); + Q_ASSERT( false ); + return; // bug + break; + } - QList< Theme::Row * >::ConstIterator end( rows->constEnd() ); - for ( QList< Theme::Row * >::ConstIterator rowit = rows->constBegin(); rowit != end; ++rowit ) - { - QSize rowSizeHint = compute_size_hint_for_row( ( *rowit ), mTheme->iconSize(), item ); + Qt::LayoutDirection layoutDir = mItemView->layoutDirection(); - int bottom = top + rowSizeHint.height(); + QList< Theme::Row * >::ConstIterator end( rows->constEnd() ); + for ( QList< Theme::Row * >::ConstIterator rowit = rows->constBegin(); rowit != end; ++rowit ) + { + QSize rowSizeHint = compute_size_hint_for_row( ( *rowit ), mTheme->iconSize(), item ); - // paint right aligned stuff first - const QList< Theme::ContentItem * > * items = &( ( *rowit )->rightItems() ); + int bottom = top + rowSizeHint.height(); - int r = right; - int l = left; - QList< Theme::ContentItem * >::ConstIterator endit( items->constEnd() ); - for ( QList< Theme::ContentItem * >::ConstIterator itemit = items->constBegin(); itemit != endit ; ++itemit ) - { - Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); + // paint right aligned stuff first + const QList< Theme::ContentItem * > * items = &( ( *rowit )->rightItems() ); - if ( ci->canUseCustomColor() ) - { - if ( ci->useCustomColor() && ( !(opt.state & QStyle::State_Selected) ) ) - { - if ( usingNonDefaultTextColor ) - { - // merge the colors - QColor nonDefault = defaultPen.color(); - QColor custom = ci->customColor(); - QColor merged( - ( nonDefault.red() + custom.red() ) >> 1, - ( nonDefault.green() + custom.green() ) >> 1, - ( nonDefault.blue() + custom.blue() ) >> 1 - ); - painter->setPen( QPen( merged ) ); - } else { - painter->setPen( QPen( ci->customColor() ) ); - } - } else - painter->setPen( defaultPen ); - } // otherwise setting a pen is useless at this time - - QFont font = itemFont( ci, item ); - - switch ( ci->type() ) - { - case Theme::ContentItem::Subject: - paint_right_aligned_elided_text( item->subject(), ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::SenderOrReceiver: - paint_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->senderOrReceiver() ), - ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::Receiver: - paint_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->receiver() ), - ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::Sender: - paint_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->sender() ), - ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::Date: - paint_right_aligned_elided_text( item->formattedDate(), ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::MostRecentDate: - paint_right_aligned_elided_text( item->formattedMaxDate(), ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::Size: - paint_right_aligned_elided_text( item->formattedSize(), ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::GroupHeaderLabel: - if ( groupHeaderItem ) - paint_right_aligned_elided_text( groupHeaderItem->label(), ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::ReadStateIcon: - paint_permanent_icon( get_read_state_icon( item ), ci, painter, l, top, r, - layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::CombinedReadRepliedStateIcon: - if ( messageItem ) - paint_permanent_icon( get_combined_read_replied_state_icon( messageItem ), ci, painter, - l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ExpandedStateIcon: + int r = right; + int l = left; + QList< Theme::ContentItem * >::ConstIterator endit( items->constEnd() ); + for ( QList< Theme::ContentItem * >::ConstIterator itemit = items->constBegin(); itemit != endit ; ++itemit ) { - const QPixmap * pix = item->childItemCount() > 0 ? ((option.state & QStyle::State_Open) ? Manager::instance()->pixmapShowLess() : Manager::instance()->pixmapShowMore()) : 0; - paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapShowMore(), - ci, painter, l, top, r, layoutDir == Qt::LeftToRight, - mTheme->iconSize() ); - } - break; - case Theme::ContentItem::RepliedStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_replied_state_icon( messageItem ); - paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageReplied(), - ci, painter, l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::EncryptionStateIcon: - if ( messageItem ) - { - bool enabled; - const QPixmap * pix = get_encryption_state_icon( messageItem, &enabled ); - paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, - layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::SignatureStateIcon: - if ( messageItem ) - { - bool enabled; - const QPixmap * pix = get_signature_state_icon( messageItem, &enabled ); - paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, + Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); + + if ( ci->canUseCustomColor() ) + { + if ( ci->useCustomColor() && ( !(opt.state & QStyle::State_Selected) ) ) + { + if ( usingNonDefaultTextColor ) + { + // merge the colors + QColor nonDefault = defaultPen.color(); + QColor custom = ci->customColor(); + QColor merged( + ( nonDefault.red() + custom.red() ) >> 1, + ( nonDefault.green() + custom.green() ) >> 1, + ( nonDefault.blue() + custom.blue() ) >> 1 + ); + painter->setPen( QPen( merged ) ); + } else { + painter->setPen( QPen( ci->customColor() ) ); + } + } else + painter->setPen( defaultPen ); + } // otherwise setting a pen is useless at this time + + QFont font = itemFont( ci, item ); + + switch ( ci->type() ) + { + case Theme::ContentItem::Subject: + paint_right_aligned_elided_text( item->subject(), ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::SenderOrReceiver: + paint_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->senderOrReceiver() ), + ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::Receiver: + paint_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->receiver() ), + ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::Sender: + paint_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->sender() ), + ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::Date: + paint_right_aligned_elided_text( item->formattedDate(), ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::MostRecentDate: + paint_right_aligned_elided_text( item->formattedMaxDate(), ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::Size: + paint_right_aligned_elided_text( item->formattedSize(), ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::GroupHeaderLabel: + if ( groupHeaderItem ) + paint_right_aligned_elided_text( groupHeaderItem->label(), ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::ReadStateIcon: + paint_permanent_icon( get_read_state_icon( item ), ci, painter, l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::SpamHamStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_spam_ham_state_icon( messageItem ); - paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageSpam(), - ci, painter, l, top, r, layoutDir == Qt::LeftToRight, - mTheme->iconSize() ); - } - break; - case Theme::ContentItem::WatchedIgnoredStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); - paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageWatched(), - ci, painter, l, top, r, layoutDir == Qt::LeftToRight, - mTheme->iconSize() ); - } - break; - case Theme::ContentItem::AttachmentStateIcon: - if ( messageItem ) - paint_boolean_state_icon( messageItem->status().hasAttachment(), - Manager::instance()->pixmapMessageAttachment(), ci, painter, - l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::AnnotationIcon: - if ( messageItem ) - paint_boolean_state_icon( messageItem->hasAnnotation(), - Manager::instance()->pixmapMessageAnnotation(), ci, painter, - l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::InvitationIcon: - if ( messageItem ) - paint_boolean_state_icon( messageItem->status().hasInvitation(), - Manager::instance()->pixmapMessageInvitation(), ci, painter, - l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ActionItemStateIcon: - if ( messageItem ) - paint_boolean_state_icon( messageItem->status().isToAct(), - Manager::instance()->pixmapMessageActionItem(), ci, painter, - l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ImportantStateIcon: - if ( messageItem ) - paint_boolean_state_icon( messageItem->status().isImportant(), - Manager::instance()->pixmapMessageImportant(), ci, painter, l, - top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::VerticalLine: - paint_vertical_line( painter, l, top, r, bottom, layoutDir == Qt::LeftToRight ); - break; - case Theme::ContentItem::HorizontalSpacer: - paint_horizontal_spacer( l, top, r, bottom, layoutDir == Qt::LeftToRight ); - break; - case Theme::ContentItem::TagList: - if ( messageItem ) - { - const QList< MessageItem::Tag * > tagList = messageItem->tagList(); - paint_tag_list( tagList, painter, l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - } - break; - } - } - - // then paint left aligned stuff - items = &( ( *rowit )->leftItems() ); - - QList< Theme::ContentItem * >::ConstIterator endItem( items->constEnd() ); - for ( QList< Theme::ContentItem * >::ConstIterator itemit = items->constBegin(); itemit != endItem ; ++itemit ) - { - Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); - - if ( ci->canUseCustomColor() ) - { - if ( ci->useCustomColor() && ( !(opt.state & QStyle::State_Selected) ) ) - { - if ( usingNonDefaultTextColor ) - { - // merge the colors - QColor nonDefault = defaultPen.color(); - QColor custom = ci->customColor(); - QColor merged( - ( nonDefault.red() + custom.red() ) >> 1, - ( nonDefault.green() + custom.green() ) >> 1, - ( nonDefault.blue() + custom.blue() ) >> 1 - ); - painter->setPen( QPen( merged ) ); - } else { - painter->setPen( QPen( ci->customColor() ) ); - } - } else { - painter->setPen( defaultPen ); + break; + case Theme::ContentItem::CombinedReadRepliedStateIcon: + if ( messageItem ) + paint_permanent_icon( get_combined_read_replied_state_icon( messageItem ), ci, painter, + l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ExpandedStateIcon: + { + const QPixmap * pix = item->childItemCount() > 0 ? ((option.state & QStyle::State_Open) ? Manager::instance()->pixmapShowLess() : Manager::instance()->pixmapShowMore()) : 0; + paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapShowMore(), + ci, painter, l, top, r, layoutDir == Qt::LeftToRight, + mTheme->iconSize() ); + } + break; + case Theme::ContentItem::RepliedStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_replied_state_icon( messageItem ); + paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageReplied(), + ci, painter, l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::EncryptionStateIcon: + if ( messageItem ) + { + bool enabled; + const QPixmap * pix = get_encryption_state_icon( messageItem, &enabled ); + paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, + layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::SignatureStateIcon: + if ( messageItem ) + { + bool enabled; + const QPixmap * pix = get_signature_state_icon( messageItem, &enabled ); + paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, + layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::SpamHamStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_spam_ham_state_icon( messageItem ); + paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageSpam(), + ci, painter, l, top, r, layoutDir == Qt::LeftToRight, + mTheme->iconSize() ); + } + break; + case Theme::ContentItem::WatchedIgnoredStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); + paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageWatched(), + ci, painter, l, top, r, layoutDir == Qt::LeftToRight, + mTheme->iconSize() ); + } + break; + case Theme::ContentItem::AttachmentStateIcon: + if ( messageItem ) + paint_boolean_state_icon( messageItem->status().hasAttachment(), + Manager::instance()->pixmapMessageAttachment(), ci, painter, + l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::AnnotationIcon: + if ( messageItem ) + paint_boolean_state_icon( messageItem->hasAnnotation(), + Manager::instance()->pixmapMessageAnnotation(), ci, painter, + l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::InvitationIcon: + if ( messageItem ) + paint_boolean_state_icon( messageItem->status().hasInvitation(), + Manager::instance()->pixmapMessageInvitation(), ci, painter, + l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ActionItemStateIcon: + if ( messageItem ) + paint_boolean_state_icon( messageItem->status().isToAct(), + Manager::instance()->pixmapMessageActionItem(), ci, painter, + l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ImportantStateIcon: + if ( messageItem ) + paint_boolean_state_icon( messageItem->status().isImportant(), + Manager::instance()->pixmapMessageImportant(), ci, painter, l, + top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::VerticalLine: + paint_vertical_line( painter, l, top, r, bottom, layoutDir == Qt::LeftToRight ); + break; + case Theme::ContentItem::HorizontalSpacer: + paint_horizontal_spacer( l, top, r, bottom, layoutDir == Qt::LeftToRight ); + break; + case Theme::ContentItem::TagList: + if ( messageItem ) + { + const QList< MessageItem::Tag * > tagList = messageItem->tagList(); + paint_tag_list( tagList, painter, l, top, r, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + } + break; + } } - } // otherwise setting a pen is useless at this time - QFont font = itemFont( ci, item ); + // then paint left aligned stuff + items = &( ( *rowit )->leftItems() ); - switch ( ci->type() ) - { - case Theme::ContentItem::Subject: - paint_left_aligned_elided_text( item->subject(), ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::SenderOrReceiver: - paint_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->senderOrReceiver() ), - ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::Receiver: - paint_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->receiver() ), - ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::Sender: - paint_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->sender() ), - ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::Date: - paint_left_aligned_elided_text( item->formattedDate(), ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::MostRecentDate: - paint_left_aligned_elided_text( item->formattedMaxDate(), ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::Size: - paint_left_aligned_elided_text( item->formattedSize(), ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::GroupHeaderLabel: - if ( groupHeaderItem ) - paint_left_aligned_elided_text( groupHeaderItem->label(), ci, painter, l, top, r, layoutDir, font ); - break; - case Theme::ContentItem::ReadStateIcon: - paint_permanent_icon( get_read_state_icon( item ), ci, painter, l, top, r, - layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::CombinedReadRepliedStateIcon: - if ( messageItem ) - paint_permanent_icon( get_combined_read_replied_state_icon( messageItem ), ci, painter, - l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ExpandedStateIcon: + QList< Theme::ContentItem * >::ConstIterator endItem( items->constEnd() ); + for ( QList< Theme::ContentItem * >::ConstIterator itemit = items->constBegin(); itemit != endItem ; ++itemit ) { - const QPixmap * pix = item->childItemCount() > 0 ? ((option.state & QStyle::State_Open) ? Manager::instance()->pixmapShowLess() : Manager::instance()->pixmapShowMore()) : 0; - paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapShowMore(), - ci, painter, l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::RepliedStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_replied_state_icon( messageItem ); - paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageReplied(), - ci, painter, l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::EncryptionStateIcon: - if ( messageItem ) - { - bool enabled; - const QPixmap * pix = get_encryption_state_icon( messageItem, &enabled ); - paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, - layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::SignatureStateIcon: - if ( messageItem ) - { - bool enabled; - const QPixmap * pix = get_signature_state_icon( messageItem, &enabled ); - paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, + Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); + + if ( ci->canUseCustomColor() ) + { + if ( ci->useCustomColor() && ( !(opt.state & QStyle::State_Selected) ) ) + { + if ( usingNonDefaultTextColor ) + { + // merge the colors + QColor nonDefault = defaultPen.color(); + QColor custom = ci->customColor(); + QColor merged( + ( nonDefault.red() + custom.red() ) >> 1, + ( nonDefault.green() + custom.green() ) >> 1, + ( nonDefault.blue() + custom.blue() ) >> 1 + ); + painter->setPen( QPen( merged ) ); + } else { + painter->setPen( QPen( ci->customColor() ) ); + } + } else { + painter->setPen( defaultPen ); + } + } // otherwise setting a pen is useless at this time + + QFont font = itemFont( ci, item ); + + switch ( ci->type() ) + { + case Theme::ContentItem::Subject: + paint_left_aligned_elided_text( item->subject(), ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::SenderOrReceiver: + paint_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->senderOrReceiver() ), + ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::Receiver: + paint_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->receiver() ), + ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::Sender: + paint_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( item->sender() ), + ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::Date: + paint_left_aligned_elided_text( item->formattedDate(), ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::MostRecentDate: + paint_left_aligned_elided_text( item->formattedMaxDate(), ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::Size: + paint_left_aligned_elided_text( item->formattedSize(), ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::GroupHeaderLabel: + if ( groupHeaderItem ) + paint_left_aligned_elided_text( groupHeaderItem->label(), ci, painter, l, top, r, layoutDir, font ); + break; + case Theme::ContentItem::ReadStateIcon: + paint_permanent_icon( get_read_state_icon( item ), ci, painter, l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::SpamHamStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_spam_ham_state_icon( messageItem ); - paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageSpam(), - ci, painter, l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::WatchedIgnoredStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); - paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageWatched(), - ci, painter, l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::AttachmentStateIcon: - if ( messageItem ) - paint_boolean_state_icon( messageItem->status().hasAttachment(), - Manager::instance()->pixmapMessageAttachment(), ci, painter, - l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::AnnotationIcon: - if ( messageItem ) - paint_boolean_state_icon( messageItem->hasAnnotation(), - Manager::instance()->pixmapMessageAnnotation(), ci, painter, - l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::InvitationIcon: - if ( messageItem ) - paint_boolean_state_icon( messageItem->status().hasInvitation(), - Manager::instance()->pixmapMessageInvitation(), ci, painter, - l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ActionItemStateIcon: - if ( messageItem ) - paint_boolean_state_icon( messageItem->status().isToAct(), - Manager::instance()->pixmapMessageActionItem(), ci, painter, - l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ImportantStateIcon: - if ( messageItem ) - paint_boolean_state_icon( messageItem->status().isImportant(), - Manager::instance()->pixmapMessageImportant(), ci, painter, l, - top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::VerticalLine: - paint_vertical_line( painter, l, top, r, bottom, layoutDir != Qt::LeftToRight ); - break; - case Theme::ContentItem::HorizontalSpacer: - paint_horizontal_spacer( l, top, r, bottom, layoutDir != Qt::LeftToRight ); - break; - case Theme::ContentItem::TagList: - if ( messageItem ) - { - const QList< MessageItem::Tag * > tagList = messageItem->tagList(); - paint_tag_list( tagList, painter, l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - } - } - - top = bottom; - } - - painter->setFont( oldFont ); - painter->setPen( oldPen ); - painter->setOpacity( oldOpacity ); + break; + case Theme::ContentItem::CombinedReadRepliedStateIcon: + if ( messageItem ) + paint_permanent_icon( get_combined_read_replied_state_icon( messageItem ), ci, painter, + l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ExpandedStateIcon: + { + const QPixmap * pix = item->childItemCount() > 0 ? ((option.state & QStyle::State_Open) ? Manager::instance()->pixmapShowLess() : Manager::instance()->pixmapShowMore()) : 0; + paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapShowMore(), + ci, painter, l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::RepliedStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_replied_state_icon( messageItem ); + paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageReplied(), + ci, painter, l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::EncryptionStateIcon: + if ( messageItem ) + { + bool enabled; + const QPixmap * pix = get_encryption_state_icon( messageItem, &enabled ); + paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, + layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::SignatureStateIcon: + if ( messageItem ) + { + bool enabled; + const QPixmap * pix = get_signature_state_icon( messageItem, &enabled ); + paint_boolean_state_icon( enabled, pix, ci, painter, l, top, r, + layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::SpamHamStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_spam_ham_state_icon( messageItem ); + paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageSpam(), + ci, painter, l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::WatchedIgnoredStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); + paint_boolean_state_icon( pix != 0, pix ? pix : Manager::instance()->pixmapMessageWatched(), + ci, painter, l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::AttachmentStateIcon: + if ( messageItem ) + paint_boolean_state_icon( messageItem->status().hasAttachment(), + Manager::instance()->pixmapMessageAttachment(), ci, painter, + l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::AnnotationIcon: + if ( messageItem ) + paint_boolean_state_icon( messageItem->hasAnnotation(), + Manager::instance()->pixmapMessageAnnotation(), ci, painter, + l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::InvitationIcon: + if ( messageItem ) + paint_boolean_state_icon( messageItem->status().hasInvitation(), + Manager::instance()->pixmapMessageInvitation(), ci, painter, + l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ActionItemStateIcon: + if ( messageItem ) + paint_boolean_state_icon( messageItem->status().isToAct(), + Manager::instance()->pixmapMessageActionItem(), ci, painter, + l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ImportantStateIcon: + if ( messageItem ) + paint_boolean_state_icon( messageItem->status().isImportant(), + Manager::instance()->pixmapMessageImportant(), ci, painter, l, + top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::VerticalLine: + paint_vertical_line( painter, l, top, r, bottom, layoutDir != Qt::LeftToRight ); + break; + case Theme::ContentItem::HorizontalSpacer: + paint_horizontal_spacer( l, top, r, bottom, layoutDir != Qt::LeftToRight ); + break; + case Theme::ContentItem::TagList: + if ( messageItem ) + { + const QList< MessageItem::Tag * > tagList = messageItem->tagList(); + paint_tag_list( tagList, painter, l, top, r, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + } + } + + top = bottom; + } + + painter->setFont( oldFont ); + painter->setPen( oldPen ); + painter->setOpacity( oldOpacity ); } bool ThemeDelegate::hitTest( const QPoint &viewportPoint, bool exact ) { - mHitItem = 0; - mHitColumn = 0; - mHitRow = 0; - mHitContentItem = 0; + mHitItem = 0; + mHitColumn = 0; + mHitRow = 0; + mHitContentItem = 0; - if ( !mTheme ) - return false; // hm hm... + if ( !mTheme ) + return false; // hm hm... - mHitIndex = mItemView->indexAt( viewportPoint ); + mHitIndex = mItemView->indexAt( viewportPoint ); - if ( !mHitIndex.isValid() ) - return false; // bleah + if ( !mHitIndex.isValid() ) + return false; // bleah - mHitItem = itemFromIndex( mHitIndex ); - if ( !mHitItem ) - return false; // hm... + mHitItem = itemFromIndex( mHitIndex ); + if ( !mHitItem ) + return false; // hm... - mHitItemRect = mItemView->visualRect( mHitIndex ); + mHitItemRect = mItemView->visualRect( mHitIndex ); - mHitColumn = mTheme->column( mHitIndex.column() ); - if ( !mHitColumn ) - return false; // bleah + mHitColumn = mTheme->column( mHitIndex.column() ); + if ( !mHitColumn ) + return false; // bleah - const QList< Theme::Row * > * rows; // I'd like to have it as reference, but gcc complains... + const QList< Theme::Row * > * rows; // I'd like to have it as reference, but gcc complains... - MessageItem * messageItem = 0; - GroupHeaderItem * groupHeaderItem = 0; + MessageItem * messageItem = 0; + GroupHeaderItem * groupHeaderItem = 0; - int top = mHitItemRect.top(); - int right = mHitItemRect.right(); - int left = mHitItemRect.left(); + int top = mHitItemRect.top(); + int right = mHitItemRect.right(); + int left = mHitItemRect.left(); - mHitRow = 0; - mHitRowIndex = -1; - mHitContentItem = 0; + mHitRow = 0; + mHitRowIndex = -1; + mHitContentItem = 0; - switch ( mHitItem->type() ) - { + switch ( mHitItem->type() ) + { case Item::Message: - mHitRowIsMessageRow = true; - rows = &( mHitColumn->messageRows() ); - messageItem = static_cast< MessageItem * >( mHitItem ); - // FIXME: paint eventual background here - - top += gMessageVerticalMargin; - right -= gMessageHorizontalMargin; - left += gMessageHorizontalMargin; - break; + mHitRowIsMessageRow = true; + rows = &( mHitColumn->messageRows() ); + messageItem = static_cast< MessageItem * >( mHitItem ); + // FIXME: paint eventual background here + + top += gMessageVerticalMargin; + right -= gMessageHorizontalMargin; + left += gMessageHorizontalMargin; + break; case Item::GroupHeader: - mHitRowIsMessageRow = false; - rows = &( mHitColumn->groupHeaderRows() ); - groupHeaderItem = static_cast< GroupHeaderItem * >( mHitItem ); - - top += gGroupHeaderOuterVerticalMargin + gGroupHeaderInnerVerticalMargin; - right -= gGroupHeaderOuterHorizontalMargin + gGroupHeaderInnerHorizontalMargin; - left += gGroupHeaderOuterHorizontalMargin + gGroupHeaderInnerHorizontalMargin; - break; + mHitRowIsMessageRow = false; + rows = &( mHitColumn->groupHeaderRows() ); + groupHeaderItem = static_cast< GroupHeaderItem * >( mHitItem ); + + top += gGroupHeaderOuterVerticalMargin + gGroupHeaderInnerVerticalMargin; + right -= gGroupHeaderOuterHorizontalMargin + gGroupHeaderInnerHorizontalMargin; + left += gGroupHeaderOuterHorizontalMargin + gGroupHeaderInnerHorizontalMargin; + break; default: - return false; // bug - break; - } - - int rowIdx = 0; - int bestInexactDistance = 0xffffff; - bool bestInexactItemRight = false; - QRect bestInexactRect; - const Theme::ContentItem * bestInexactContentItem = 0; - - Qt::LayoutDirection layoutDir = mItemView->layoutDirection(); - - QList< Theme::Row * >::ConstIterator end( rows->constEnd() ); - for ( QList< Theme::Row * >::ConstIterator rowit = rows->constBegin(); rowit != end; ++rowit ) - { - QSize rowSizeHint = compute_size_hint_for_row( ( *rowit ), mTheme->iconSize(), mHitItem ); + return false; // bug + break; + } - if ( ( viewportPoint.y() < top ) && ( rowIdx > 0 ) ) - break; // not this row (tough we should have already found it... probably clicked upper margin) + int rowIdx = 0; + int bestInexactDistance = 0xffffff; + bool bestInexactItemRight = false; + QRect bestInexactRect; + const Theme::ContentItem * bestInexactContentItem = 0; - int bottom = top + rowSizeHint.height(); + Qt::LayoutDirection layoutDir = mItemView->layoutDirection(); - if ( viewportPoint.y() > bottom ) + QList< Theme::Row * >::ConstIterator end( rows->constEnd() ); + for ( QList< Theme::Row * >::ConstIterator rowit = rows->constBegin(); rowit != end; ++rowit ) { - top += rowSizeHint.height(); - rowIdx++; - continue; // not this row - } - - bestInexactItemRight = false; - bestInexactDistance = 0xffffff; - bestInexactContentItem = 0; + QSize rowSizeHint = compute_size_hint_for_row( ( *rowit ), mTheme->iconSize(), mHitItem ); - // this row! - mHitRow = *rowit; - mHitRowIndex = rowIdx; - mHitRowRect = QRect( left, top, right - left, bottom - top ); + if ( ( viewportPoint.y() < top ) && ( rowIdx > 0 ) ) + break; // not this row (tough we should have already found it... probably clicked upper margin) - // check right aligned stuff first - const QList< Theme::ContentItem * > * items = &( mHitRow->rightItems() ); - QList< Theme::ContentItem * >::ConstIterator itemit; + int bottom = top + rowSizeHint.height(); - mHitContentItemRight = true; + if ( viewportPoint.y() > bottom ) + { + top += rowSizeHint.height(); + rowIdx++; + continue; // not this row + } - int r = right; - int l = left; - QList< Theme::ContentItem * >::ConstIterator itemEnd( items->end() ); + bestInexactItemRight = false; + bestInexactDistance = 0xffffff; + bestInexactContentItem = 0; + + // this row! + mHitRow = *rowit; + mHitRowIndex = rowIdx; + mHitRowRect = QRect( left, top, right - left, bottom - top ); + + // check right aligned stuff first + const QList< Theme::ContentItem * > * items = &( mHitRow->rightItems() ); + QList< Theme::ContentItem * >::ConstIterator itemit; + + mHitContentItemRight = true; + + int r = right; + int l = left; + QList< Theme::ContentItem * >::ConstIterator itemEnd( items->end() ); - for ( itemit = items->begin(); itemit != itemEnd ; ++itemit ) - { - Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); + for ( itemit = items->begin(); itemit != itemEnd ; ++itemit ) + { + Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); - mHitContentItemRect = QRect(); + mHitContentItemRect = QRect(); - QFont font = itemFont( ci, mHitItem ); + QFont font = itemFont( ci, mHitItem ); - switch ( ci->type() ) - { - case Theme::ContentItem::Subject: - compute_bounding_rect_for_right_aligned_elided_text( mHitItem->subject(), l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::SenderOrReceiver: - compute_bounding_rect_for_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->senderOrReceiver() ), - l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::Receiver: - compute_bounding_rect_for_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->receiver() ), - l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::Sender: - compute_bounding_rect_for_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->sender() ), - l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::Date: - compute_bounding_rect_for_right_aligned_elided_text( mHitItem->formattedDate(), l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::MostRecentDate: - compute_bounding_rect_for_right_aligned_elided_text( mHitItem->formattedMaxDate(), l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::Size: - compute_bounding_rect_for_right_aligned_elided_text( mHitItem->formattedSize(), l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::GroupHeaderLabel: - if ( groupHeaderItem ) - compute_bounding_rect_for_right_aligned_elided_text( groupHeaderItem->label(), l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::ReadStateIcon: - compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::CombinedReadRepliedStateIcon: - compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ExpandedStateIcon: - compute_bounding_rect_for_boolean_state_icon( mHitItem->childItemCount() > 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::RepliedStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_replied_state_icon( messageItem ); - compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::EncryptionStateIcon: - if ( messageItem ) - { - bool enabled; - get_encryption_state_icon( messageItem, &enabled ); - compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::SignatureStateIcon: - if ( messageItem ) - { - bool enabled; - get_signature_state_icon( messageItem, &enabled ); - compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::SpamHamStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_spam_ham_state_icon( messageItem ); - compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::WatchedIgnoredStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); - compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::AttachmentStateIcon: - if ( messageItem ) - compute_bounding_rect_for_boolean_state_icon( messageItem->status().hasAttachment(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::AnnotationIcon: - if ( messageItem ) - compute_bounding_rect_for_boolean_state_icon( messageItem->hasAnnotation(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::InvitationIcon: - if ( messageItem ) - compute_bounding_rect_for_boolean_state_icon( messageItem->status().hasInvitation(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ActionItemStateIcon: - if ( messageItem ) - compute_bounding_rect_for_boolean_state_icon( messageItem->status().isToAct(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ImportantStateIcon: - if ( messageItem ) - compute_bounding_rect_for_boolean_state_icon( messageItem->status().isImportant(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::VerticalLine: - compute_bounding_rect_for_vertical_line( l, top, r, bottom, mHitContentItemRect, layoutDir == Qt::LeftToRight ); - break; - case Theme::ContentItem::HorizontalSpacer: - compute_bounding_rect_for_horizontal_spacer( l, top, r, bottom, mHitContentItemRect, layoutDir == Qt::LeftToRight ); - break; - case Theme::ContentItem::TagList: - if ( messageItem ) - { - const QList< MessageItem::Tag * > tagList = messageItem->tagList(); - compute_bounding_rect_for_tag_list( tagList, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); - } - break; - } + switch ( ci->type() ) + { + case Theme::ContentItem::Subject: + compute_bounding_rect_for_right_aligned_elided_text( mHitItem->subject(), l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::SenderOrReceiver: + compute_bounding_rect_for_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->senderOrReceiver() ), + l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::Receiver: + compute_bounding_rect_for_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->receiver() ), + l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::Sender: + compute_bounding_rect_for_right_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->sender() ), + l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::Date: + compute_bounding_rect_for_right_aligned_elided_text( mHitItem->formattedDate(), l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::MostRecentDate: + compute_bounding_rect_for_right_aligned_elided_text( mHitItem->formattedMaxDate(), l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::Size: + compute_bounding_rect_for_right_aligned_elided_text( mHitItem->formattedSize(), l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::GroupHeaderLabel: + if ( groupHeaderItem ) + compute_bounding_rect_for_right_aligned_elided_text( groupHeaderItem->label(), l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::ReadStateIcon: + compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::CombinedReadRepliedStateIcon: + compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ExpandedStateIcon: + compute_bounding_rect_for_boolean_state_icon( mHitItem->childItemCount() > 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::RepliedStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_replied_state_icon( messageItem ); + compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::EncryptionStateIcon: + if ( messageItem ) + { + bool enabled; + get_encryption_state_icon( messageItem, &enabled ); + compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::SignatureStateIcon: + if ( messageItem ) + { + bool enabled; + get_signature_state_icon( messageItem, &enabled ); + compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::SpamHamStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_spam_ham_state_icon( messageItem ); + compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::WatchedIgnoredStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); + compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::AttachmentStateIcon: + if ( messageItem ) + compute_bounding_rect_for_boolean_state_icon( messageItem->status().hasAttachment(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::AnnotationIcon: + if ( messageItem ) + compute_bounding_rect_for_boolean_state_icon( messageItem->hasAnnotation(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::InvitationIcon: + if ( messageItem ) + compute_bounding_rect_for_boolean_state_icon( messageItem->status().hasInvitation(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ActionItemStateIcon: + if ( messageItem ) + compute_bounding_rect_for_boolean_state_icon( messageItem->status().isToAct(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ImportantStateIcon: + if ( messageItem ) + compute_bounding_rect_for_boolean_state_icon( messageItem->status().isImportant(), ci, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::VerticalLine: + compute_bounding_rect_for_vertical_line( l, top, r, bottom, mHitContentItemRect, layoutDir == Qt::LeftToRight ); + break; + case Theme::ContentItem::HorizontalSpacer: + compute_bounding_rect_for_horizontal_spacer( l, top, r, bottom, mHitContentItemRect, layoutDir == Qt::LeftToRight ); + break; + case Theme::ContentItem::TagList: + if ( messageItem ) + { + const QList< MessageItem::Tag * > tagList = messageItem->tagList(); + compute_bounding_rect_for_tag_list( tagList, l, top, r, mHitContentItemRect, layoutDir == Qt::LeftToRight, mTheme->iconSize() ); + } + break; + } - if ( mHitContentItemRect.isValid() ) - { - if ( mHitContentItemRect.contains( viewportPoint ) ) - { - // caught! - mHitContentItem = ci; - return true; - } - if ( !exact ) - { - QRect inexactRect( mHitContentItemRect.left(), mHitRowRect.top(), mHitContentItemRect.width(), mHitRowRect.height() ); - if ( inexactRect.contains( viewportPoint ) ) - { - mHitContentItem = ci; - return true; - } - - int inexactDistance = viewportPoint.x() > inexactRect.right() ? viewportPoint.x() - inexactRect.right() : inexactRect.left() - viewportPoint.x(); - if ( inexactDistance < bestInexactDistance ) - { - bestInexactDistance = inexactDistance; - bestInexactRect = mHitContentItemRect; - bestInexactItemRight = true; - bestInexactContentItem = ci; - } + if ( mHitContentItemRect.isValid() ) + { + if ( mHitContentItemRect.contains( viewportPoint ) ) + { + // caught! + mHitContentItem = ci; + return true; + } + if ( !exact ) + { + QRect inexactRect( mHitContentItemRect.left(), mHitRowRect.top(), mHitContentItemRect.width(), mHitRowRect.height() ); + if ( inexactRect.contains( viewportPoint ) ) + { + mHitContentItem = ci; + return true; + } + + int inexactDistance = viewportPoint.x() > inexactRect.right() ? viewportPoint.x() - inexactRect.right() : inexactRect.left() - viewportPoint.x(); + if ( inexactDistance < bestInexactDistance ) + { + bestInexactDistance = inexactDistance; + bestInexactRect = mHitContentItemRect; + bestInexactItemRight = true; + bestInexactContentItem = ci; + } + } + } } - } - } - // then check left aligned stuff - items = &( mHitRow->leftItems() ); + // then check left aligned stuff + items = &( mHitRow->leftItems() ); - mHitContentItemRight = false; + mHitContentItemRight = false; - for ( itemit = items->constBegin(); itemit != items->constEnd() ; ++itemit ) - { - Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); + for ( itemit = items->constBegin(); itemit != items->constEnd() ; ++itemit ) + { + Theme::ContentItem * ci = const_cast< Theme::ContentItem * >( *itemit ); - mHitContentItemRect = QRect(); + mHitContentItemRect = QRect(); - QFont font = itemFont( ci, mHitItem ); + QFont font = itemFont( ci, mHitItem ); - switch ( ci->type() ) - { - case Theme::ContentItem::Subject: - compute_bounding_rect_for_left_aligned_elided_text( mHitItem->subject(), l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::SenderOrReceiver: - compute_bounding_rect_for_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->senderOrReceiver() ), - l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::Receiver: - compute_bounding_rect_for_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->receiver() ), - l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::Sender: - compute_bounding_rect_for_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->sender() ), - l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::Date: - compute_bounding_rect_for_left_aligned_elided_text( mHitItem->formattedDate(), l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::MostRecentDate: - compute_bounding_rect_for_left_aligned_elided_text( mHitItem->formattedMaxDate(), l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::Size: - compute_bounding_rect_for_left_aligned_elided_text( mHitItem->formattedSize(), l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::GroupHeaderLabel: - if ( groupHeaderItem ) - compute_bounding_rect_for_left_aligned_elided_text( groupHeaderItem->label(), l, top, r, mHitContentItemRect, layoutDir, font ); - break; - case Theme::ContentItem::ReadStateIcon: - compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::CombinedReadRepliedStateIcon: - compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ExpandedStateIcon: - compute_bounding_rect_for_boolean_state_icon( mHitItem->childItemCount() > 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::RepliedStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_replied_state_icon( messageItem ); - compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::EncryptionStateIcon: - if ( messageItem ) - { - bool enabled; - get_encryption_state_icon( messageItem, &enabled ); - compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::SignatureStateIcon: - if ( messageItem ) - { - bool enabled; - get_signature_state_icon( messageItem, &enabled ); - compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::SpamHamStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_spam_ham_state_icon( messageItem ); - compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::WatchedIgnoredStateIcon: - if ( messageItem ) - { - const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); - compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - case Theme::ContentItem::AttachmentStateIcon: - if ( messageItem ) - compute_bounding_rect_for_boolean_state_icon( messageItem->status().hasAttachment(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::AnnotationIcon: - if ( messageItem ) - compute_bounding_rect_for_boolean_state_icon( messageItem->hasAnnotation(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::InvitationIcon: - if ( messageItem ) - compute_bounding_rect_for_boolean_state_icon( messageItem->status().hasInvitation(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ActionItemStateIcon: - if ( messageItem ) - compute_bounding_rect_for_boolean_state_icon( messageItem->status().isToAct(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::ImportantStateIcon: - if ( messageItem ) - compute_bounding_rect_for_boolean_state_icon( messageItem->status().isImportant(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - break; - case Theme::ContentItem::VerticalLine: - compute_bounding_rect_for_vertical_line( l, top, r, bottom, mHitContentItemRect, layoutDir != Qt::LeftToRight ); - break; - case Theme::ContentItem::HorizontalSpacer: - compute_bounding_rect_for_horizontal_spacer( l, top, r, bottom, mHitContentItemRect, layoutDir != Qt::LeftToRight ); - break; - case Theme::ContentItem::TagList: - if ( messageItem ) - { - const QList< MessageItem::Tag * > tagList = messageItem->tagList(); - compute_bounding_rect_for_tag_list( tagList, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); - } - break; - } + switch ( ci->type() ) + { + case Theme::ContentItem::Subject: + compute_bounding_rect_for_left_aligned_elided_text( mHitItem->subject(), l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::SenderOrReceiver: + compute_bounding_rect_for_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->senderOrReceiver() ), + l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::Receiver: + compute_bounding_rect_for_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->receiver() ), + l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::Sender: + compute_bounding_rect_for_left_aligned_elided_text( MessageCore::StringUtil::stripEmailAddr( mHitItem->sender() ), + l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::Date: + compute_bounding_rect_for_left_aligned_elided_text( mHitItem->formattedDate(), l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::MostRecentDate: + compute_bounding_rect_for_left_aligned_elided_text( mHitItem->formattedMaxDate(), l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::Size: + compute_bounding_rect_for_left_aligned_elided_text( mHitItem->formattedSize(), l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::GroupHeaderLabel: + if ( groupHeaderItem ) + compute_bounding_rect_for_left_aligned_elided_text( groupHeaderItem->label(), l, top, r, mHitContentItemRect, layoutDir, font ); + break; + case Theme::ContentItem::ReadStateIcon: + compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::CombinedReadRepliedStateIcon: + compute_bounding_rect_for_permanent_icon( ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ExpandedStateIcon: + compute_bounding_rect_for_boolean_state_icon( mHitItem->childItemCount() > 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::RepliedStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_replied_state_icon( messageItem ); + compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::EncryptionStateIcon: + if ( messageItem ) + { + bool enabled; + get_encryption_state_icon( messageItem, &enabled ); + compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::SignatureStateIcon: + if ( messageItem ) + { + bool enabled; + get_signature_state_icon( messageItem, &enabled ); + compute_bounding_rect_for_boolean_state_icon( enabled, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::SpamHamStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_spam_ham_state_icon( messageItem ); + compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::WatchedIgnoredStateIcon: + if ( messageItem ) + { + const QPixmap * pix = get_watched_ignored_state_icon( messageItem ); + compute_bounding_rect_for_boolean_state_icon( pix != 0, ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + case Theme::ContentItem::AttachmentStateIcon: + if ( messageItem ) + compute_bounding_rect_for_boolean_state_icon( messageItem->status().hasAttachment(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::AnnotationIcon: + if ( messageItem ) + compute_bounding_rect_for_boolean_state_icon( messageItem->hasAnnotation(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::InvitationIcon: + if ( messageItem ) + compute_bounding_rect_for_boolean_state_icon( messageItem->status().hasInvitation(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ActionItemStateIcon: + if ( messageItem ) + compute_bounding_rect_for_boolean_state_icon( messageItem->status().isToAct(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::ImportantStateIcon: + if ( messageItem ) + compute_bounding_rect_for_boolean_state_icon( messageItem->status().isImportant(), ci, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + break; + case Theme::ContentItem::VerticalLine: + compute_bounding_rect_for_vertical_line( l, top, r, bottom, mHitContentItemRect, layoutDir != Qt::LeftToRight ); + break; + case Theme::ContentItem::HorizontalSpacer: + compute_bounding_rect_for_horizontal_spacer( l, top, r, bottom, mHitContentItemRect, layoutDir != Qt::LeftToRight ); + break; + case Theme::ContentItem::TagList: + if ( messageItem ) + { + const QList< MessageItem::Tag * > tagList = messageItem->tagList(); + compute_bounding_rect_for_tag_list( tagList, l, top, r, mHitContentItemRect, layoutDir != Qt::LeftToRight, mTheme->iconSize() ); + } + break; + } - if ( mHitContentItemRect.isValid() ) - { - if ( mHitContentItemRect.contains( viewportPoint ) ) - { - // caught! - mHitContentItem = ci; - return true; - } - if ( !exact ) - { - QRect inexactRect( mHitContentItemRect.left(), mHitRowRect.top(), mHitContentItemRect.width(), mHitRowRect.height() ); - if ( inexactRect.contains( viewportPoint ) ) - { - mHitContentItem = ci; - return true; - } - - int inexactDistance = viewportPoint.x() > inexactRect.right() ? viewportPoint.x() - inexactRect.right() : inexactRect.left() - viewportPoint.x(); - if ( inexactDistance < bestInexactDistance ) - { - bestInexactDistance = inexactDistance; - bestInexactRect = mHitContentItemRect; - bestInexactItemRight = false; - bestInexactContentItem = ci; - } + if ( mHitContentItemRect.isValid() ) + { + if ( mHitContentItemRect.contains( viewportPoint ) ) + { + // caught! + mHitContentItem = ci; + return true; + } + if ( !exact ) + { + QRect inexactRect( mHitContentItemRect.left(), mHitRowRect.top(), mHitContentItemRect.width(), mHitRowRect.height() ); + if ( inexactRect.contains( viewportPoint ) ) + { + mHitContentItem = ci; + return true; + } + + int inexactDistance = viewportPoint.x() > inexactRect.right() ? viewportPoint.x() - inexactRect.right() : inexactRect.left() - viewportPoint.x(); + if ( inexactDistance < bestInexactDistance ) + { + bestInexactDistance = inexactDistance; + bestInexactRect = mHitContentItemRect; + bestInexactItemRight = false; + bestInexactContentItem = ci; + } + } + } } - } - } - top += rowSizeHint.height(); - rowIdx++; - } + top += rowSizeHint.height(); + rowIdx++; + } - mHitContentItem = bestInexactContentItem; - mHitContentItemRight = bestInexactItemRight; - mHitContentItemRect = bestInexactRect; - return true; + mHitContentItem = bestInexactContentItem; + mHitContentItemRight = bestInexactItemRight; + mHitContentItemRect = bestInexactRect; + return true; } QSize ThemeDelegate::sizeHintForItemTypeAndColumn( Item::Type type, int column, const Item *item ) const { - if ( !mTheme ) - return QSize( 16, 16 ); // bleah + if ( !mTheme ) + return QSize( 16, 16 ); // bleah - const Theme::Column * skcolumn = mTheme->column( column ); - if ( !skcolumn ) - return QSize( 16, 16 ); // bleah + const Theme::Column * skcolumn = mTheme->column( column ); + if ( !skcolumn ) + return QSize( 16, 16 ); // bleah - const QList< Theme::Row * > * rows; // I'd like to have it as reference, but gcc complains... + const QList< Theme::Row * > * rows; // I'd like to have it as reference, but gcc complains... - // The sizeHint() is layout direction independent. + // The sizeHint() is layout direction independent. - int marginw; - int marginh; + int marginw; + int marginh; - switch ( type ) - { + switch ( type ) + { case Item::Message: { - rows = &( skcolumn->messageRows() ); + rows = &( skcolumn->messageRows() ); - marginh = gMessageVerticalMargin << 1; - marginw = gMessageHorizontalMargin << 1; + marginh = gMessageVerticalMargin << 1; + marginw = gMessageHorizontalMargin << 1; } - break; + break; case Item::GroupHeader: { - rows = &( skcolumn->groupHeaderRows() ); + rows = &( skcolumn->groupHeaderRows() ); - marginh = ( gGroupHeaderOuterVerticalMargin + gGroupHeaderInnerVerticalMargin ) << 1; - marginw = ( gGroupHeaderOuterVerticalMargin + gGroupHeaderInnerVerticalMargin ) << 1; + marginh = ( gGroupHeaderOuterVerticalMargin + gGroupHeaderInnerVerticalMargin ) << 1; + marginw = ( gGroupHeaderOuterVerticalMargin + gGroupHeaderInnerVerticalMargin ) << 1; } - break; + break; default: - return QSize( 16, 16 ); // bug - break; - } - - int totalh = 0; - int maxw = 0; - - for ( QList< Theme::Row * >::ConstIterator rowit = rows->constBegin(), endRowIt = rows->constEnd(); rowit != endRowIt; ++rowit ) - { - QSize sh = compute_size_hint_for_row( ( *rowit ), mTheme->iconSize(), item ); - totalh += sh.height(); - if ( sh.width() > maxw ) - maxw = sh.width(); - } + return QSize( 16, 16 ); // bug + break; + } + + int totalh = 0; + int maxw = 0; + + for ( QList< Theme::Row * >::ConstIterator rowit = rows->constBegin(), endRowIt = rows->constEnd(); rowit != endRowIt; ++rowit ) + { + QSize sh = compute_size_hint_for_row( ( *rowit ), mTheme->iconSize(), item ); + totalh += sh.height(); + if ( sh.width() > maxw ) + maxw = sh.width(); + } - return QSize( maxw + marginw , totalh + marginh ); + return QSize( maxw + marginw , totalh + marginh ); } QSize ThemeDelegate::sizeHint( const QStyleOptionViewItem &, const QModelIndex & index ) const { - if ( !mTheme ) - return QSize( 16, 16 ); // hm hm... + if ( !mTheme ) + return QSize( 16, 16 ); // hm hm... - if ( !index.isValid() ) - return QSize( 16, 16 ); // bleah + if ( !index.isValid() ) + return QSize( 16, 16 ); // bleah - Item * item = itemFromIndex( index ); - if ( !item ) - return QSize( 16, 16 ); // hm... + Item * item = itemFromIndex( index ); + if ( !item ) + return QSize( 16, 16 ); // hm... - //Item::Type type = item->type(); + //Item::Type type = item->type(); - return sizeHintForItemTypeAndColumn( item->type(), index.column(), item ); + return sizeHintForItemTypeAndColumn( item->type(), index.column(), item ); } QFont ThemeDelegate::itemFont( const Theme::ContentItem *ci, const Item *item ) { - if ( ci && ci->useCustomFont() ) - return ci->font(); + if ( ci && ci->useCustomFont() ) + return ci->font(); - if ( item && ( item->type() == Item::Message ) ) - return static_cast< const MessageItem * >( item )->font(); + if ( item && ( item->type() == Item::Message ) ) + return static_cast< const MessageItem * >( item )->font(); - return KGlobalSettings::generalFont(); + return KGlobalSettings::generalFont(); } class ThemeDelegateStaticData @@ -1682,19 +1682,19 @@ QString ThemeDelegate::itemFontKey( const Theme::ContentItem *ci, const Item *item ) { - if ( ci && ci->useCustomFont() ) - return ci->fontKey(); + if ( ci && ci->useCustomFont() ) + return ci->fontKey(); - if ( item && ( item->type() == Item::Message ) ) - return static_cast< const MessageItem * >( item )->fontKey(); + if ( item && ( item->type() == Item::Message ) ) + return static_cast< const MessageItem * >( item )->fontKey(); - return s_static->mGeneralFontKey; + return s_static->mGeneralFontKey; } // Store the new fontKey when the generalFont changes. void ThemeDelegate::slotGeneralFontChanged() { - s_static->mGeneralFontKey = KGlobalSettings::generalFont().key(); + s_static->mGeneralFontKey = KGlobalSettings::generalFont().key(); } diff -Nru kdepim-4.12.97/messagelist/core/themedelegate.h kdepim-4.13.0/messagelist/core/themedelegate.h --- kdepim-4.12.97/messagelist/core/themedelegate.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/themedelegate.h 2014-04-10 07:40:20.000000000 +0000 @@ -44,43 +44,43 @@ */ class ThemeDelegate : public QStyledItemDelegate { - Q_OBJECT + Q_OBJECT public: - explicit ThemeDelegate( QAbstractItemView * parent ); - ~ThemeDelegate(); + explicit ThemeDelegate( QAbstractItemView * parent ); + ~ThemeDelegate(); private: - const Theme * mTheme; ///< Shallow pointer to the current theme - QAbstractItemView * mItemView; + const Theme * mTheme; ///< Shallow pointer to the current theme + QAbstractItemView * mItemView; - QColor mGroupHeaderBackgroundColor; // cache + QColor mGroupHeaderBackgroundColor; // cache - // hitTest results - QModelIndex mHitIndex; - Item * mHitItem; - QRect mHitItemRect; - const Theme::Column * mHitColumn; - const Theme::Row * mHitRow; - int mHitRowIndex; - bool mHitRowIsMessageRow; - QRect mHitRowRect; - bool mHitContentItemRight; - const Theme::ContentItem * mHitContentItem; - QRect mHitContentItemRect; + // hitTest results + QModelIndex mHitIndex; + Item * mHitItem; + QRect mHitItemRect; + const Theme::Column * mHitColumn; + const Theme::Row * mHitRow; + int mHitRowIndex; + bool mHitRowIsMessageRow; + QRect mHitRowRect; + bool mHitContentItemRight; + const Theme::ContentItem * mHitContentItem; + QRect mHitContentItemRect; public: - const Theme * theme() const + const Theme * theme() const { return mTheme; } - void setTheme( const Theme * theme ); + void setTheme( const Theme * theme ); - /** + /** * Returns a heuristic sizeHint() for the specified item type and column. * The hint is based on the contents of the theme (and not of any message or group header). */ - QSize sizeHintForItemTypeAndColumn( Item::Type type, int column, const Item *item = 0) const; + QSize sizeHintForItemTypeAndColumn( Item::Type type, int column, const Item *item = 0) const; - /** + /** * Performs a hit test on the specified viewport point. * Returns true if the point hit something and false otherwise. * When the hit test is succesfull then the hitIndex(), hitItem(), hitColumn(), hitRow(), and hitContentItem() @@ -90,137 +90,137 @@ * will do its best to find the closest object to be actually "hit": this is useful, * for example, in drag and drop operations. */ - bool hitTest( const QPoint &viewportPoint, bool exact = true ); + bool hitTest( const QPoint &viewportPoint, bool exact = true ); - /** + /** * Returns the model index that was reported as hit by the previous call to hitTest(). * The result of this function is valid only if hitTest() returned true and only * within the same calling function. */ - const QModelIndex & hitIndex() const + const QModelIndex & hitIndex() const { return mHitIndex; } - /** + /** * Returns the Item that was reported as hit by the previous call to hitTest(). * The result of this function is valid only if hitTest() returned true and only * within the same calling function. */ - Item * hitItem() const + Item * hitItem() const { return mHitItem; } - /** + /** * Returns the visual rectangle of the item that was reported as hit by the previous call to hitTest(). * The result of this function is valid only if hitTest() returned true and only * within the same calling function. Please note that this rectangle refers * to a specific item column (and not all of the columns). */ - QRect hitItemRect() const + QRect hitItemRect() const { return mHitItemRect; } - /** + /** * Returns the theme column that was reported as hit by the previous call to hitTest(). * The result of this function is valid only if hitTest() returned true and only * within the same calling function. */ - const Theme::Column * hitColumn() const + const Theme::Column * hitColumn() const { return mHitColumn; } - /** + /** * Returns the index of the theme column that was reported as hit by the previous call to hitTest(). * The result of this function is valid only if hitTest() returned true and only * within the same calling function. * This is the same as hitIndex().column(). */ - int hitColumnIndex() const + int hitColumnIndex() const { return mHitIndex.column(); } - /** + /** * Returns the theme row that was reported as hit by the previous call to hitTest(). * The result of this function is valid only if hitTest() returned true and only * within the same calling function. This function may also return a null row * when hitTest() returned true. This means that the item was globally hit * but no row was exactly hit (the user probably hit the margin instead). */ - const Theme::Row * hitRow() const + const Theme::Row * hitRow() const { return mHitRow; } - /** + /** * Returns the index of the theme row that was reported as hit by the previous call to hitTest(). * The result of this function is valid only if hitRow() returns a non null value. */ - int hitRowIndex() const + int hitRowIndex() const { return mHitRowIndex; } - /** + /** * Returns the rectangle of the row that was reported as hit by the previous call to hitTest(). * The result of this function is valid only if hitTest() returned true and only * within the same calling function. The result of this function is also invalid * if hitRow() returns 0. */ - QRect hitRowRect() const + QRect hitRowRect() const { return mHitRowRect; } - /** + /** * Returns true if the hitRow() is a message row, false otherwise. * The result of this function has a meaning only if hitRow() returns a non zero result. */ - bool hitRowIsMessageRow() const + bool hitRowIsMessageRow() const { return mHitRowIsMessageRow; } - /** + /** * Returns the theme content item that was reported as hit by the previous call to hitTest(). * The result of this function is valid only if hitTest() returned true and only * within the same calling function. This function may also return a null content item * when hitTest() returned true. This means that the item was globally hit * but no content item was exactly hit (the user might have clicked inside a blank unused space instead). */ - const Theme::ContentItem * hitContentItem() const + const Theme::ContentItem * hitContentItem() const { return mHitContentItem; } - /** + /** * Returns true if the hit theme content item was a right item and false otherwise. * The result of this function is valid only if hitContentItem() returns true. */ - bool hitContentItemRight() const + bool hitContentItemRight() const { return mHitContentItemRight; } - /** + /** * Returns the bounding rect of the content item that was reported as hit by the previous call to hitTest(). * The result of this function is valid only if hitTest() returned true and only * within the same calling function. The result of this function is to be considered * invalid also when hitContentItem() returns 0. */ - QRect hitContentItemRect() const + QRect hitContentItemRect() const { return mHitContentItemRect; } - /// return the font to paint given item with, checking global kmail settings and theme settings - static QFont itemFont( const Theme::ContentItem *ci, const Item *item ); + /// return the font to paint given item with, checking global kmail settings and theme settings + static QFont itemFont( const Theme::ContentItem *ci, const Item *item ); - /// return the font key to paint given item with, checking global kmail settings and theme settings - static QString itemFontKey( const Theme::ContentItem *ci, const Item *item ); + /// return the font key to paint given item with, checking global kmail settings and theme settings + static QString itemFontKey( const Theme::ContentItem *ci, const Item *item ); protected: - /** + /** * Returns the Item for the specified model index. Pure virtual: must be reimplemented * by derived classes. */ - virtual Item * itemFromIndex( const QModelIndex &index ) const = 0; + virtual Item * itemFromIndex( const QModelIndex &index ) const = 0; - /** + /** * Reimplemented from QStyledItemDelegate */ - void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; + void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; - /** + /** * Reimplemented from QStyledItemDelegate */ - QSize sizeHint( const QStyleOptionViewItem & option, const QModelIndex & index ) const; + QSize sizeHint( const QStyleOptionViewItem & option, const QModelIndex & index ) const; private slots: - /** + /** * Called when the global fonts change (from systemsettings) */ - void slotGeneralFontChanged(); + void slotGeneralFontChanged(); }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/theme.h kdepim-4.13.0/messagelist/core/theme.h --- kdepim-4.12.97/messagelist/core/theme.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/theme.h 2014-04-10 07:40:20.000000000 +0000 @@ -65,1003 +65,1003 @@ class Theme : public OptionSet { public: - /** + /** * The ContentItem class defines a content item inside a Row. * Content items are data items extracted from a message or a group header: * they can be text, spacers, separators or icons. */ - class ContentItem - { - private: - /** + class ContentItem + { + private: + /** * Bits for composing the Type enumeration members. * We'll be able to test these bits to quickly figure out item properties. */ - enum TypePropertyBits - { - /** + enum TypePropertyBits + { + /** * Item can use the custom color property */ - CanUseCustomColor = (1 << 16), - /** + CanUseCustomColor = (1 << 16), + /** * Item can be in a disabled state (for example the attachment icon when there is no attachment) */ - CanBeDisabled = (1 << 17), - /** + CanBeDisabled = (1 << 17), + /** * Item displays some sort of text */ - DisplaysText = (1 << 18), - /** + DisplaysText = (1 << 18), + /** * Item makes sense (and can be applied) for messages */ - ApplicableToMessageItems = (1 << 19), - /** + ApplicableToMessageItems = (1 << 19), + /** * Item makes sense (and can be applied) for group headers */ - ApplicableToGroupHeaderItems = (1 << 20), - /** + ApplicableToGroupHeaderItems = (1 << 20), + /** * The item takes more horizontal space than the other text items (at the time of writing it's only the subject) */ - LongText = (1 << 21), - /** + LongText = (1 << 21), + /** * The item displays an icon */ - IsIcon = (1 << 22), - /** + IsIcon = (1 << 22), + /** * The item is a small spacer */ - IsSpacer = (1 << 23), - /** + IsSpacer = (1 << 23), + /** * The item is clickable */ - IsClickable = (1 << 24) - }; + IsClickable = (1 << 24) + }; - public: - /** + public: + /** * The available ContentItem types. * Note that the values in this enum are unique values or'ed with the TypePropertyBits above. */ - enum Type - { - /** + enum Type + { + /** * Display the subject of the message item. This is a long text. */ - Subject = 1 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | LongText, - /** + Subject = 1 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | LongText, + /** * Formatted date time of the message/group */ - Date = 2 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems, - /** + Date = 2 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems, + /** * From: or To: strip, depending on the folder settings */ - SenderOrReceiver = 3 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, - /** + SenderOrReceiver = 3 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, + /** * From: strip, always */ - Sender = 4 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, - /** + Sender = 4 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, + /** * To: strip, always */ - Receiver = 5 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, - /** + Receiver = 5 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, + /** * Formatted size of the message */ - Size = 6 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, - /** + Size = 6 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, + /** * The icon that displays the unread/read state (never disabled) */ - ReadStateIcon = 7 | ApplicableToMessageItems | IsIcon, - /** + ReadStateIcon = 7 | ApplicableToMessageItems | IsIcon, + /** * The icon that displays the atachment state (may be disabled) */ - AttachmentStateIcon = 8 | CanBeDisabled | ApplicableToMessageItems | IsIcon, - /** + AttachmentStateIcon = 8 | CanBeDisabled | ApplicableToMessageItems | IsIcon, + /** * The icon that displays the replied/forwarded state (may be disabled) */ - RepliedStateIcon = 9 | CanBeDisabled | ApplicableToMessageItems | IsIcon, - /** + RepliedStateIcon = 9 | CanBeDisabled | ApplicableToMessageItems | IsIcon, + /** * The group header label */ - GroupHeaderLabel = 10 | DisplaysText | CanUseCustomColor | ApplicableToGroupHeaderItems, - /** + GroupHeaderLabel = 10 | DisplaysText | CanUseCustomColor | ApplicableToGroupHeaderItems, + /** * The ActionItem state icon. May be disabled. Clickable (cycles todo->nothing) */ - ActionItemStateIcon = 11 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, - /** + ActionItemStateIcon = 11 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, + /** * The Important tag icon. May be disabled. Clickable (cycles important->nothing) */ - ImportantStateIcon = 12 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, - /** + ImportantStateIcon = 12 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, + /** * The Spam/Ham state icon. May be disabled. Clickable (cycles spam->ham->nothing) */ - SpamHamStateIcon = 13 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, - /** + SpamHamStateIcon = 13 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, + /** * The Watched/Ignored state icon. May be disabled. Clickable (cycles watched->ignored->nothing) */ - WatchedIgnoredStateIcon = 14 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, - /** + WatchedIgnoredStateIcon = 14 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, + /** * The Expanded state icon for group headers. May be disabled. Clickable (expands/collapses the group) */ - ExpandedStateIcon = 15 | CanBeDisabled | ApplicableToGroupHeaderItems | IsIcon | IsClickable, - /** + ExpandedStateIcon = 15 | CanBeDisabled | ApplicableToGroupHeaderItems | IsIcon | IsClickable, + /** * The Encryption state icon for messages. May be disabled (no encryption). */ - EncryptionStateIcon = 16 | CanBeDisabled | ApplicableToMessageItems | IsIcon, - /** + EncryptionStateIcon = 16 | CanBeDisabled | ApplicableToMessageItems | IsIcon, + /** * The Signature state icon for messages. May be disabled (no signature) */ - SignatureStateIcon = 17 | CanBeDisabled | ApplicableToMessageItems | IsIcon, - /** + SignatureStateIcon = 17 | CanBeDisabled | ApplicableToMessageItems | IsIcon, + /** * A vertical separation line. */ - VerticalLine = 18 | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems | IsSpacer, - /** + VerticalLine = 18 | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems | IsSpacer, + /** * A small empty spacer usable as separator. */ - HorizontalSpacer = 19 | ApplicableToMessageItems | ApplicableToGroupHeaderItems | IsSpacer, - /** + HorizontalSpacer = 19 | ApplicableToMessageItems | ApplicableToGroupHeaderItems | IsSpacer, + /** * The date of the most recent message in subtree */ - MostRecentDate = 20 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems, - /** + MostRecentDate = 20 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems, + /** * The combined icon that displays the unread/read/replied/forwarded state (never disabled) */ - CombinedReadRepliedStateIcon = 21 | ApplicableToMessageItems | IsIcon, - /** + CombinedReadRepliedStateIcon = 21 | ApplicableToMessageItems | IsIcon, + /** * The list of MessageItem::Tag entries */ - TagList = 22 | ApplicableToMessageItems | IsIcon, - /** + TagList = 22 | ApplicableToMessageItems | IsIcon, + /** * Whether the message has a annotation/note */ - AnnotationIcon = 23 | ApplicableToMessageItems | IsIcon | CanBeDisabled | IsClickable, + AnnotationIcon = 23 | ApplicableToMessageItems | IsIcon | CanBeDisabled | IsClickable, - /** + /** * Whether the message is an invitation */ - InvitationIcon = 24 | ApplicableToMessageItems | IsIcon + InvitationIcon = 24 | ApplicableToMessageItems | IsIcon #if 0 - TotalMessageCount - UnreadMessageCount - NewMessageCount + TotalMessageCount + UnreadMessageCount + NewMessageCount #endif - }; + }; - enum Flags - { - HideWhenDisabled = 1, ///< In disabled state the icon should take no space (overrides SoftenByBlendingWhenDisabled) - SoftenByBlendingWhenDisabled = (1 << 1), ///< In disabled state the icon should be still shown, but made very soft by alpha blending - UseCustomColor = (1 << 2), ///< For text and vertical line. If set then always use a custom color, otherwise use default text color - UseCustomFont = (1 << 3), ///< For text items. If set then always use a custom font, otherwise default to the global font. - SoftenByBlending = (1 << 4) ///< For text items: use 60% opacity. - }; + enum Flags + { + HideWhenDisabled = 1, ///< In disabled state the icon should take no space (overrides SoftenByBlendingWhenDisabled) + SoftenByBlendingWhenDisabled = (1 << 1), ///< In disabled state the icon should be still shown, but made very soft by alpha blending + UseCustomColor = (1 << 2), ///< For text and vertical line. If set then always use a custom color, otherwise use default text color + UseCustomFont = (1 << 3), ///< For text items. If set then always use a custom font, otherwise default to the global font. + SoftenByBlending = (1 << 4) ///< For text items: use 60% opacity. + }; + + private: + Type mType; ///< The type of item + unsigned int mFlags; ///< The flags of the item + + QFont mFont; ///< The font to use with this content item, meaningful only if displaysText() returns true. + QString mFontKey; ///< The font key to speedup theme positioning. QFont.key() is called too many times otherwise. + QColor mCustomColor; ///< The color to use with this content item, meaningful only if canUseCustomColor() return true. - private: - Type mType; ///< The type of item - unsigned int mFlags; ///< The flags of the item - - QFont mFont; ///< The font to use with this content item, meaningful only if displaysText() returns true. - QString mFontKey; ///< The font key to speedup theme positioning. QFont.key() is called too many times otherwise. - QColor mCustomColor; ///< The color to use with this content item, meaningful only if canUseCustomColor() return true. - - public: - /** + public: + /** * Creates a ContentItem with the specified type. * A content item must be added to a theme Row. */ - explicit ContentItem( Type type ); - /** + explicit ContentItem( Type type ); + /** * Creates a ContentItem that is a copy of the content item src. * A content item must be added to a theme Row. */ - explicit ContentItem( const ContentItem &src ); + explicit ContentItem( const ContentItem &src ); - public: - /** + public: + /** * Returns the type of this content item */ - Type type() const - { return mType; } + Type type() const + { return mType; } - /** + /** * Returns true if this ContentItem can be in a "disabled" state. * The attachment state icon, for example, can be disabled when the related * message has no attachments. For such items the HideWhenDisabled * and SoftenByBlendingWhenDisabled flags are meaningful. */ - bool canBeDisabled() const - { return ( static_cast< int >( mType ) & CanBeDisabled ) != 0; } + bool canBeDisabled() const + { return ( static_cast< int >( mType ) & CanBeDisabled ) != 0; } - /** + /** * Returns true if this ContentItem can make use of a custom color. */ - bool canUseCustomColor() const - { return ( static_cast< int >( mType ) & CanUseCustomColor ) != 0; } + bool canUseCustomColor() const + { return ( static_cast< int >( mType ) & CanUseCustomColor ) != 0; } - /** + /** * Returns true if this item displays some kind of text. * Items that display text make use of the customFont() setting. */ - bool displaysText() const - { return ( static_cast< int >( mType ) & DisplaysText ) != 0; } + bool displaysText() const + { return ( static_cast< int >( mType ) & DisplaysText ) != 0; } - /** + /** * Returns true if this item displays a long text. * The returned value makes sense only if displaysText() returned true. */ - bool displaysLongText() const - { return ( static_cast< int >( mType ) & LongText ) != 0; } + bool displaysLongText() const + { return ( static_cast< int >( mType ) & LongText ) != 0; } - /** + /** * Returns true if this item displays an icon. */ - bool isIcon() const - { return ( static_cast< int >( mType ) & IsIcon ) != 0; } - /** + bool isIcon() const + { return ( static_cast< int >( mType ) & IsIcon ) != 0; } + /** * Returns true if clicking on this kind of item can perform an action */ - bool isClickable() const - { return ( static_cast< int >( mType ) & IsClickable ) != 0; } + bool isClickable() const + { return ( static_cast< int >( mType ) & IsClickable ) != 0; } - /** + /** * Returns true if this item is a small spacer */ - bool isSpacer() const - { return ( static_cast< int >( mType ) & IsSpacer ) != 0; } + bool isSpacer() const + { return ( static_cast< int >( mType ) & IsSpacer ) != 0; } - /** + /** * Static test that returns true if an instance of ContentItem with the * specified type makes sense in a Row for message items. */ - static bool applicableToMessageItems( Type type ); + static bool applicableToMessageItems( Type type ); - /** + /** * Static test that returns true if an instance of ContentItem with the * specified type makes sense in a Row for group header items. */ - static bool applicableToGroupHeaderItems( Type type ); + static bool applicableToGroupHeaderItems( Type type ); - /** + /** * Returns a descriptive name for the specified content item type */ - static QString description( Type type ); + static QString description( Type type ); - /** + /** * Returns true if this item uses a custom color. * The return value of this function is valid only if canUseCustomColor() returns true. */ - bool useCustomColor() const - { return mFlags & UseCustomColor; } + bool useCustomColor() const + { return mFlags & UseCustomColor; } - /** + /** * Makes this item use the custom color that can be set by setCustomColor(). * The custom color is meaningful only if canUseCustomColor() returns true. */ - void setUseCustomColor( bool useCustomColor ) - { if ( useCustomColor )mFlags |= UseCustomColor; else mFlags &= ~UseCustomColor; } + void setUseCustomColor( bool useCustomColor ) + { if ( useCustomColor )mFlags |= UseCustomColor; else mFlags &= ~UseCustomColor; } - /** + /** * Returns true if this item uses a custom font. * The return value of this function is valid only if displaysText() returns true. */ - bool useCustomFont() const - { return mFlags & UseCustomFont; } + bool useCustomFont() const + { return mFlags & UseCustomFont; } - /** + /** * Makes this item use the custom font that can be set by setCustomFont(). * The custom font is meaningful only if canUseCustomFont() returns true. */ - void setUseCustomFont( bool useCustomFont ) - { if ( useCustomFont )mFlags |= UseCustomFont; else mFlags &= ~UseCustomFont; } + void setUseCustomFont( bool useCustomFont ) + { if ( useCustomFont )mFlags |= UseCustomFont; else mFlags &= ~UseCustomFont; } - /** + /** * Returns true if this item should be hidden when in disabled state. * Hidden content items simply aren't painted and take no space. * This flag has meaning only on items for that canBeDisabled() returns true. */ - bool hideWhenDisabled() const - { return mFlags & HideWhenDisabled; } + bool hideWhenDisabled() const + { return mFlags & HideWhenDisabled; } - /** + /** * Sets the flag that causes this item to be hidden when disabled. * Hidden content items simply aren't painted and take no space. * This flag overrides the setSoftenByBlendingWhenDisabled() setting. * This flag has meaning only on items for that canBeDisabled() returns true. */ - void setHideWhenDisabled( bool hideWhenDisabled ) - { if ( hideWhenDisabled )mFlags |= HideWhenDisabled; else mFlags &= ~HideWhenDisabled; } + void setHideWhenDisabled( bool hideWhenDisabled ) + { if ( hideWhenDisabled )mFlags |= HideWhenDisabled; else mFlags &= ~HideWhenDisabled; } - /** + /** * Returns true if this item should be painted in a "soft" fashion when * in disabled state. Soft icons are painted with very low opacity. * This flag has meaning only on items for that canBeDisabled() returns true. */ - bool softenByBlendingWhenDisabled() const - { return mFlags & SoftenByBlendingWhenDisabled; } + bool softenByBlendingWhenDisabled() const + { return mFlags & SoftenByBlendingWhenDisabled; } - /** + /** * Sets the flag that causes this item to be painted "softly" when disabled. * Soft icons are painted with very low opacity. * This flag may be overridden by the setHideWhenDisabled() setting. * This flag has meaning only on items for that canBeDisabled() returns true. */ - void setSoftenByBlendingWhenDisabled( bool softenByBlendingWhenDisabled ) - { if ( softenByBlendingWhenDisabled )mFlags |= SoftenByBlendingWhenDisabled; else mFlags &= ~SoftenByBlendingWhenDisabled; } + void setSoftenByBlendingWhenDisabled( bool softenByBlendingWhenDisabled ) + { if ( softenByBlendingWhenDisabled )mFlags |= SoftenByBlendingWhenDisabled; else mFlags &= ~SoftenByBlendingWhenDisabled; } - /** + /** * Returns true if this item should be always painted in a "soft" fashion. * Meaningful only for text items. */ - bool softenByBlending() const - { return mFlags & SoftenByBlending; } + bool softenByBlending() const + { return mFlags & SoftenByBlending; } - /** + /** * Sets the flag that causes this item to be painted "softly". * Meaningful only for text items. */ - void setSoftenByBlending( bool softenByBlending ) - { if ( softenByBlending )mFlags |= SoftenByBlending; else mFlags &= ~SoftenByBlending; } + void setSoftenByBlending( bool softenByBlending ) + { if ( softenByBlending )mFlags |= SoftenByBlending; else mFlags &= ~SoftenByBlending; } - /** + /** * Sets the custom font to be used with this item. * The font is meaningful only for items for that displaysText() returns true. * You must also call setUseCustomFont() in order for this setting to be effective. */ - void setFont( const QFont &font ); + void setFont( const QFont &font ); - /** + /** * Returns the font used by this item. It may be a custom font set by setFont() * or the default application font (returned by KGlobalSettings::generalFont()). * This setting is valid as long as you have called updateFontMetrics() * with the appropriate paint device. */ - const QFont & font() const - { return mFont; } + const QFont & font() const + { return mFont; } - /** + /** * Returns the font key used by this item. It may be a custom font key set by setFont() * or the default application font (returned by KGlobalSettings::generalFont()). * This setting is valid as long as you have called updateFontMetrics() * with the appropriate paint device. * It is primary used to avoid to calculate the key every time an item is displayed. */ - const QString & fontKey() const - { return mFontKey; } + const QString & fontKey() const + { return mFontKey; } - /** + /** * Returns the custom color set for this item. * The return value is meaningful only if canUseCustomColor() returns true * returns true and setUseCustomColor( true ) has been called. */ - const QColor & customColor() const - { return mCustomColor; } + const QColor & customColor() const + { return mCustomColor; } - /** + /** * Sets the custom color for this item. Meaningful only if canUseCustomColor() * returns true and you call setUseCustomColor( true ) */ - void setCustomColor( const QColor &clr ) - { mCustomColor = clr; } + void setCustomColor( const QColor &clr ) + { mCustomColor = clr; } - // Stuff used by ThemeDelegate. This section should be protected but some gcc - // versions seem to get confused with nested class and friend declarations - // so for portability we're using a public interface also here. + // Stuff used by ThemeDelegate. This section should be protected but some gcc + // versions seem to get confused with nested class and friend declarations + // so for portability we're using a public interface also here. - /** + /** * Handles content item saving (used by Theme::Row::save()) */ - void save( QDataStream &stream ) const; + void save( QDataStream &stream ) const; - /** + /** * Handles content item loading (used by Theme::Row::load()) */ - bool load( QDataStream &stream, int themeVersion ); - }; + bool load( QDataStream &stream, int themeVersion ); + }; - /** + /** * The Row class defines a row of items inside a Column. * The Row has a list of left aligned and a list of right aligned ContentItems. */ - class Row - { - public: - explicit Row(); - explicit Row( const Row &src ); - ~Row(); - - private: - QList< ContentItem * > mLeftItems; ///< The list of left aligned items - QList< ContentItem * > mRightItems; ///< The list of right aligned items + class Row + { + public: + explicit Row(); + explicit Row( const Row &src ); + ~Row(); + + private: + QList< ContentItem * > mLeftItems; ///< The list of left aligned items + QList< ContentItem * > mRightItems; ///< The list of right aligned items - bool LoadContentItem(int val, QDataStream &stream, int themeVersion, bool leftItem); - public: - /** + bool LoadContentItem(int val, QDataStream &stream, int themeVersion, bool leftItem); + public: + /** * Returns the list of left aligned items for this row */ - const QList< ContentItem * > & leftItems() const - { return mLeftItems; } + const QList< ContentItem * > & leftItems() const + { return mLeftItems; } - /** + /** * Removes all the left items from this row: the items are deleted. */ - void removeAllLeftItems(); + void removeAllLeftItems(); - /** + /** * Adds a left aligned item to this row. The row takes the ownership * of the ContentItem pointer. */ - void addLeftItem( ContentItem * item ) - { mLeftItems.append( item ); } + void addLeftItem( ContentItem * item ) + { mLeftItems.append( item ); } - /** + /** * Adds a left aligned item at the specified position in this row. The row takes the ownership * of the ContentItem pointer. */ - void insertLeftItem( int idx, ContentItem * item ); + void insertLeftItem( int idx, ContentItem * item ); - /** + /** * Removes the specified left aligned content item from this row. * The item is NOT deleted. */ - void removeLeftItem( ContentItem * item ) - { mLeftItems.removeAll( item ); } + void removeLeftItem( ContentItem * item ) + { mLeftItems.removeAll( item ); } - /** + /** * Returns the list of right aligned items for this row */ - const QList< ContentItem * > & rightItems() const - { return mRightItems; } + const QList< ContentItem * > & rightItems() const + { return mRightItems; } - /** + /** * Removes all the right items from this row. The items are deleted. */ - void removeAllRightItems(); + void removeAllRightItems(); - /** + /** * Adds a right aligned item to this row. The row takes the ownership * of the ContentItem pointer. Please note that the first right aligned item * will start at the right edge, the second right aligned item will come after it etc... */ - void addRightItem( ContentItem * item ) - { mRightItems.append( item ); } + void addRightItem( ContentItem * item ) + { mRightItems.append( item ); } - /** + /** * Adds a right aligned item at the specified position in this row. The row takes the ownership * of the ContentItem pointer. Remember that right item positions go from right to left. */ - void insertRightItem( int idx, ContentItem * item ); + void insertRightItem( int idx, ContentItem * item ); - /** + /** * Removes the specified right aligned content item from this row. * The item is NOT deleted. */ - void removeRightItem( ContentItem * item ) - { mRightItems.removeAll( item ); } + void removeRightItem( ContentItem * item ) + { mRightItems.removeAll( item ); } - /** + /** * Returns true if this row contains text items. * This is useful if you want to know if the column should just get * its minimum allowable space or it should get more. */ - bool containsTextItems() const; + bool containsTextItems() const; - /** + /** * Handles row saving (used by Theme::Column::save()) */ - void save( QDataStream &stream ) const; + void save( QDataStream &stream ) const; - /** + /** * Handles row loading (used by Theme::Column::load()) */ - bool load( QDataStream &stream, int themeVersion ); + bool load( QDataStream &stream, int themeVersion ); - }; + }; - /** + /** * The Column class defines a view column available inside this theme. * Each Column has a list of Row items that define the visible rows. */ - class Column - { - public: - /** + class Column + { + public: + /** * A set of shared runtime data. This is used to store a set of "override" settings * at runtime. For instance, the width of the visible columns of a skin are stored here. */ - class SharedRuntimeData - { - private: - int mReferences; ///< The number of external references to this shared data object - - int mCurrentlyVisible; ///< Is this column currently visible ? always valid (eventually set from default) - int mCurrentWidth; ///< The current width of this column, -1 if not valid (never set) - public: - /** + class SharedRuntimeData + { + private: + int mReferences; ///< The number of external references to this shared data object + + int mCurrentlyVisible; ///< Is this column currently visible ? always valid (eventually set from default) + int mCurrentWidth; ///< The current width of this column, -1 if not valid (never set) + public: + /** * Create a shared runtime data object */ - explicit SharedRuntimeData( bool currentlyVisible, int currentWidth ); + explicit SharedRuntimeData( bool currentlyVisible, int currentWidth ); - /** + /** * Destroy a shared runtime data object */ - ~SharedRuntimeData(); - public: - /** + ~SharedRuntimeData(); + public: + /** * Increments the reference count for this shared runtime data object. */ - void addReference(); + void addReference(); - /** + /** * Decrements the reference count for this shared runtime data object. * Returns true if there are other references and false otherwise (so the data can be safely deleted) */ - bool deleteReference(); + bool deleteReference(); - /** + /** * Returns the current number of reference counts, that is, the number of * Theme::Column objects that use this SharedRuntimeData instance. */ - int referenceCount() const - { return mReferences; } + int referenceCount() const + { return mReferences; } - /** + /** * Returns the current visibility state */ - bool currentlyVisible() const - { return mCurrentlyVisible; } + bool currentlyVisible() const + { return mCurrentlyVisible; } - /** + /** * Sets the current visibility state */ - void setCurrentlyVisible( bool visible ) - { mCurrentlyVisible = visible; } + void setCurrentlyVisible( bool visible ) + { mCurrentlyVisible = visible; } - /** + /** * Returns the current width or -1 if the width is unspecified/invalid */ - int currentWidth() const - { return mCurrentWidth; } + int currentWidth() const + { return mCurrentWidth; } - /** + /** * Sets the current width of the column */ - void setCurrentWidth( int currentWidth ) - { mCurrentWidth = currentWidth; } + void setCurrentWidth( int currentWidth ) + { mCurrentWidth = currentWidth; } - /** + /** * Saves this runtime data to the specified stream */ - void save( QDataStream &stream ) const; + void save( QDataStream &stream ) const; - /** + /** * Loads the shared runtime data from the specified stream * assuming that it uses the specified theme version. * Returns true on success and false if the data can't be loaded. */ - bool load( QDataStream &stream, int themeVersion ); - }; - public: - /** + bool load( QDataStream &stream, int themeVersion ); + }; + public: + /** * Create an empty column with default settings */ - explicit Column(); - /** + explicit Column(); + /** * Create an exact copy of the column src. * The shared runtime data is not copied (only a reference is added). * If you need to create an independent clone then please use detach() * after the construction. */ - explicit Column( const Column &src ); - /** + explicit Column( const Column &src ); + /** * Kill a column object */ - ~Column(); + ~Column(); - private: - QString mLabel; ///< The label visible in the column header - QString mPixmapName; ///< The icon's name visible in the column header if it was set - bool mVisibleByDefault; ///< Is this column visible by default ? - bool mIsSenderOrReceiver; ///< If this column displays the sender/receiver field then we will update its label on the fly - SortOrder::MessageSorting mMessageSorting; ///< The message sort order we switch to when clicking on this column - QList< Row * > mGroupHeaderRows; ///< The list of rows we display in this column for a GroupHeaderItem - QList< Row * > mMessageRows; ///< The list of rows we display in this column for a MessageItem + private: + QString mLabel; ///< The label visible in the column header + QString mPixmapName; ///< The icon's name visible in the column header if it was set + bool mVisibleByDefault; ///< Is this column visible by default ? + bool mIsSenderOrReceiver; ///< If this column displays the sender/receiver field then we will update its label on the fly + SortOrder::MessageSorting mMessageSorting; ///< The message sort order we switch to when clicking on this column + QList< Row * > mGroupHeaderRows; ///< The list of rows we display in this column for a GroupHeaderItem + QList< Row * > mMessageRows; ///< The list of rows we display in this column for a MessageItem - SharedRuntimeData * mSharedRuntimeData; ///< A pointer to the shared runtime data: shared between all instances of a theme with the same id - public: - /** + SharedRuntimeData * mSharedRuntimeData; ///< A pointer to the shared runtime data: shared between all instances of a theme with the same id + public: + /** * Returns the label set for this column */ - const QString & label() const - { return mLabel; } + const QString & label() const + { return mLabel; } - /** + /** * Sets the label for this column */ - void setLabel( const QString &label ) - { mLabel = label; } + void setLabel( const QString &label ) + { mLabel = label; } - /** + /** * Returns the icon's name (used in SmallIcon) set for this column */ - const QString & pixmapName() const - { return mPixmapName; } + const QString & pixmapName() const + { return mPixmapName; } - /** + /** * Sets the icon's name (used in SmallIcon) for this column */ - void setPixmapName( const QString &pixmapName ) - { mPixmapName = pixmapName; } + void setPixmapName( const QString &pixmapName ) + { mPixmapName = pixmapName; } - /** + /** * Returns true if this column is marked as "sender/receiver" and we should * update its label on-the-fly. */ - bool isSenderOrReceiver() const - { return mIsSenderOrReceiver; } + bool isSenderOrReceiver() const + { return mIsSenderOrReceiver; } - /** + /** * Marks this column as containing the "sender/receiver" field. * Such columns will have the label automatically updated. */ - void setIsSenderOrReceiver( bool sor ) - { mIsSenderOrReceiver = sor; } + void setIsSenderOrReceiver( bool sor ) + { mIsSenderOrReceiver = sor; } - /** + /** * Returns true if this column has to be shown by default */ - bool visibleByDefault() const - { return mVisibleByDefault; } + bool visibleByDefault() const + { return mVisibleByDefault; } - /** + /** * Sets the "visible by default" tag for this column. */ - void setVisibleByDefault( bool vbd ) - { mVisibleByDefault = vbd; } + void setVisibleByDefault( bool vbd ) + { mVisibleByDefault = vbd; } - /** + /** * Detaches the shared runtime data object and makes this object * totally independent. The shared runtime data is initialized to default values. */ - void detach(); + void detach(); - /** + /** * Returns the sort order for messages that we should switch to * when clicking on this column's header (if visible at all). */ - SortOrder::MessageSorting messageSorting() const - { return mMessageSorting; } + SortOrder::MessageSorting messageSorting() const + { return mMessageSorting; } - /** + /** * Sets the sort order for messages that we should switch to * when clicking on this column's header (if visible at all). */ - void setMessageSorting( SortOrder::MessageSorting ms ) - { mMessageSorting = ms; } + void setMessageSorting( SortOrder::MessageSorting ms ) + { mMessageSorting = ms; } - /** + /** * Returns the current shared visibility state for this column. * This state is shared between all the instances of this theme. */ - bool currentlyVisible() const - { return mSharedRuntimeData->currentlyVisible(); } + bool currentlyVisible() const + { return mSharedRuntimeData->currentlyVisible(); } - /** + /** * Sets the current shared visibility state for this column. * This state is shared between all the instances of this theme. */ - void setCurrentlyVisible( bool currentlyVisible ) - { mSharedRuntimeData->setCurrentlyVisible( currentlyVisible ); } + void setCurrentlyVisible( bool currentlyVisible ) + { mSharedRuntimeData->setCurrentlyVisible( currentlyVisible ); } - /** + /** * Returns the current shared width setting for this column * or -1 if the width is not specified and should be auto-determined. * This state is shared between all the instances of this theme. */ - int currentWidth() const - { return mSharedRuntimeData->currentWidth(); } + int currentWidth() const + { return mSharedRuntimeData->currentWidth(); } - /** + /** * Sets the current shared width setting for this column. * This state is shared between all the instances of this theme. */ - void setCurrentWidth( int currentWidth ) - { mSharedRuntimeData->setCurrentWidth( currentWidth ); } + void setCurrentWidth( int currentWidth ) + { mSharedRuntimeData->setCurrentWidth( currentWidth ); } - /** + /** * Returns the list of rows visible in this column for a MessageItem */ - const QList< Row * > & messageRows() const - { return mMessageRows; } + const QList< Row * > & messageRows() const + { return mMessageRows; } - /** + /** * Removes all the message rows from this column. */ - void removeAllMessageRows(); + void removeAllMessageRows(); - /** + /** * Appends a message row to this theme column. The Theme takes * the ownership of the Row pointer. */ - void addMessageRow( Row * row ) - { mMessageRows.append( row ); } + void addMessageRow( Row * row ) + { mMessageRows.append( row ); } - /** + /** * Inserts a message row to this theme column in the specified position. The Theme takes * the ownership of the Row pointer. */ - void insertMessageRow( int idx, Row * row ); + void insertMessageRow( int idx, Row * row ); - /** + /** * Removes the specified message row. The row is NOT deleted. */ - void removeMessageRow( Row * row ) - { mMessageRows.removeAll( row ); } + void removeMessageRow( Row * row ) + { mMessageRows.removeAll( row ); } - /** + /** * Returns the list of rows visible in this column for a GroupHeaderItem */ - const QList< Row * > & groupHeaderRows() const - { return mGroupHeaderRows; } + const QList< Row * > & groupHeaderRows() const + { return mGroupHeaderRows; } - /** + /** * Removes all the group header rows from this column. */ - void removeAllGroupHeaderRows(); + void removeAllGroupHeaderRows(); - /** + /** * Appends a group header row to this theme. The Theme takes * the ownership of the Row pointer. */ - void addGroupHeaderRow( Row * row ) - { mGroupHeaderRows.append( row ); } + void addGroupHeaderRow( Row * row ) + { mGroupHeaderRows.append( row ); } - /** + /** * Inserts a group header row to this theme column in the specified position. The Theme takes * the ownership of the Row pointer. */ - void insertGroupHeaderRow( int idx, Row * row ); + void insertGroupHeaderRow( int idx, Row * row ); - /** + /** * Removes the specified group header row. The row is NOT deleted. */ - void removeGroupHeaderRow( Row * row ) - { mGroupHeaderRows.removeAll( row ); } + void removeGroupHeaderRow( Row * row ) + { mGroupHeaderRows.removeAll( row ); } - /** + /** * Returns true if this column contains text items. * This is useful if you want to know if the column should just get * its minimum allowable space or it should get more. */ - bool containsTextItems() const; + bool containsTextItems() const; - /** + /** * Handles column saving (used by Theme::save()) */ - void save( QDataStream &stream ) const; + void save( QDataStream &stream ) const; - /** + /** * Handles column loading (used by Theme::load()) */ - bool load( QDataStream &stream, int themeVersion ); + bool load( QDataStream &stream, int themeVersion ); - }; + }; public: - /** + /** * Creates a totally uninitialized theme object. */ - explicit Theme(); + explicit Theme(); - /** + /** * Creates a theme object with the specified name and description. */ - explicit Theme( const QString &name, const QString &description, bool readOnly = false ); + explicit Theme( const QString &name, const QString &description, bool readOnly = false ); - /** + /** * Creates an exact copy of the theme sharing the same runtime data. * If you need an exact clone please use detach() and generateUniqueId() just * after creation. */ - explicit Theme( const Theme &src ); + explicit Theme( const Theme &src ); - /** + /** * Destroys this theme object. */ - ~Theme(); + ~Theme(); - static bool compareName( Theme *theme1, Theme *theme2 ) - { - return ( theme1->name() < theme2->name() ); - } + static bool compareName( Theme *theme1, Theme *theme2 ) + { + return ( theme1->name() < theme2->name() ); + } public: - /** + /** * Which color do we use to paint group header background ? */ - enum GroupHeaderBackgroundMode - { - Transparent, ///< No background at all: use style default - AutoColor, ///< Automatically determine the color (somewhere in the middle between background and text) - CustomColor ///< Use a custom color - }; + enum GroupHeaderBackgroundMode + { + Transparent, ///< No background at all: use style default + AutoColor, ///< Automatically determine the color (somewhere in the middle between background and text) + CustomColor ///< Use a custom color + }; - /** + /** * How do we paint group header background ? */ - enum GroupHeaderBackgroundStyle - { - PlainRect, ///< One plain rect per column - PlainJoinedRect, ///< One big plain rect for all the columns - RoundedRect, ///< One rounded rect per column - RoundedJoinedRect, ///< One big rounded rect for all the columns - GradientRect, ///< One rounded gradient filled rect per column - GradientJoinedRect, ///< One big rounded gradient rect for all the columns - StyledRect, ///< One styled rect per column - StyledJoinedRect ///< One big styled rect per column - }; + enum GroupHeaderBackgroundStyle + { + PlainRect, ///< One plain rect per column + PlainJoinedRect, ///< One big plain rect for all the columns + RoundedRect, ///< One rounded rect per column + RoundedJoinedRect, ///< One big rounded rect for all the columns + GradientRect, ///< One rounded gradient filled rect per column + GradientJoinedRect, ///< One big rounded gradient rect for all the columns + StyledRect, ///< One styled rect per column + StyledJoinedRect ///< One big styled rect per column + }; - /** + /** * How do we manage the QHeaderView attacched to our View ? */ - enum ViewHeaderPolicy - { - ShowHeaderAlways, - NeverShowHeader - //ShowWhenMoreThanOneColumn, ///< This doesn't work at the moment (since without header we don't have means for showing columns back) - }; + enum ViewHeaderPolicy + { + ShowHeaderAlways, + NeverShowHeader + //ShowWhenMoreThanOneColumn, ///< This doesn't work at the moment (since without header we don't have means for showing columns back) + }; private: - QList< Column * > mColumns; ///< The list of columns available in this theme + QList< Column * > mColumns; ///< The list of columns available in this theme - GroupHeaderBackgroundMode mGroupHeaderBackgroundMode; ///< How do we paint group header background ? - QColor mGroupHeaderBackgroundColor; ///< The background color of the message group, used only if CustomColor - GroupHeaderBackgroundStyle mGroupHeaderBackgroundStyle; ///< How do we paint group header background ? - ViewHeaderPolicy mViewHeaderPolicy; ///< Do we show the header or not ? - int mIconSize; ///< The icon size for this theme, 16 is the default + GroupHeaderBackgroundMode mGroupHeaderBackgroundMode; ///< How do we paint group header background ? + QColor mGroupHeaderBackgroundColor; ///< The background color of the message group, used only if CustomColor + GroupHeaderBackgroundStyle mGroupHeaderBackgroundStyle; ///< How do we paint group header background ? + ViewHeaderPolicy mViewHeaderPolicy; ///< Do we show the header or not ? + int mIconSize; ///< The icon size for this theme, 16 is the default public: - /** + /** * Detaches this object from the shared runtime data for columns. */ - void detach(); + void detach(); - /** + /** * Resets the column state (visibility and width) to their default values (the "visible by default" ones). */ - void resetColumnState(); + void resetColumnState(); - /** + /** * Resets the column sizes to "default" (subset of resetColumnState() above). */ - void resetColumnSizes(); + void resetColumnSizes(); - /** + /** * Returns the list of columns available in this theme */ - const QList< Column * > & columns() const + const QList< Column * > & columns() const { return mColumns; } - /** + /** * Returns a pointer to the column at the specified index or 0 if there is no such column */ - Column * column( int idx ) const + Column * column( int idx ) const { return mColumns.count() > idx ? mColumns.at( idx ) : 0; } - void moveColumn(int idx, int newPosition); + void moveColumn(int idx, int newPosition); - /** + /** * Removes all columns from this theme */ - void removeAllColumns(); + void removeAllColumns(); - /** + /** * Appends a column to this theme */ - void addColumn( Column * column ) + void addColumn( Column * column ) { mColumns.append( column ); } - /** + /** * Inserts a column to this theme at the specified position. */ - void insertColumn( int idx, Column * column ); + void insertColumn( int idx, Column * column ); - /** + /** * Removes the specified message row. The row is NOT deleted. */ - void removeColumn( Column * col ) + void removeColumn( Column * col ) { mColumns.removeAll( col ); } - /** + /** * Returns the group header background mode for this theme. */ - GroupHeaderBackgroundMode groupHeaderBackgroundMode() const + GroupHeaderBackgroundMode groupHeaderBackgroundMode() const { return mGroupHeaderBackgroundMode; } - /** + /** * Sets the group header background mode for this theme. * If you set it to CustomColor then please also setGroupHeaderBackgroundColor() */ - void setGroupHeaderBackgroundMode( GroupHeaderBackgroundMode bm ); + void setGroupHeaderBackgroundMode( GroupHeaderBackgroundMode bm ); - /** + /** * Returns the group header background color for this theme. * This color is used only if groupHeaderBackgroundMode() is set to CustomColor. */ - const QColor & groupHeaderBackgroundColor() const + const QColor & groupHeaderBackgroundColor() const { return mGroupHeaderBackgroundColor; } - /** + /** * Sets the group header background color for this theme. * This color is used only if groupHeaderBackgroundMode() is set to CustomColor. */ - void setGroupHeaderBackgroundColor( const QColor &clr ) + void setGroupHeaderBackgroundColor( const QColor &clr ) { mGroupHeaderBackgroundColor = clr; } - /** + /** * Returns the group header background style for this theme. * The group header background style makes sense only if groupHeaderBackgroundMode() is * set to something different than Transparent. */ - GroupHeaderBackgroundStyle groupHeaderBackgroundStyle() const + GroupHeaderBackgroundStyle groupHeaderBackgroundStyle() const { return mGroupHeaderBackgroundStyle; } - /** + /** * Sets the group header background style for this theme. * The group header background style makes sense only if groupHeaderBackgroundMode() is * set to something different than Transparent. */ - void setGroupHeaderBackgroundStyle( GroupHeaderBackgroundStyle groupHeaderBackgroundStyle ) + void setGroupHeaderBackgroundStyle( GroupHeaderBackgroundStyle groupHeaderBackgroundStyle ) { mGroupHeaderBackgroundStyle = groupHeaderBackgroundStyle; } - /** + /** * Enumerates the available group header background styles. * The returned descriptors are pairs in that the first item is the localized description * of the option value and the second item is the integer option value itself. */ - static QList< QPair< QString, int > > enumerateGroupHeaderBackgroundStyles(); + static QList< QPair< QString, int > > enumerateGroupHeaderBackgroundStyles(); - /** + /** * Returns the currently set ViewHeaderPolicy */ - ViewHeaderPolicy viewHeaderPolicy() const + ViewHeaderPolicy viewHeaderPolicy() const { return mViewHeaderPolicy; } - /** + /** * Sets the ViewHeaderPolicy for this theme */ - void setViewHeaderPolicy( ViewHeaderPolicy vhp ) + void setViewHeaderPolicy( ViewHeaderPolicy vhp ) { mViewHeaderPolicy = vhp; } - /** + /** * Returns the currently set icon size */ - int iconSize() const + int iconSize() const { return mIconSize; } - /** + /** * Sets the icon size for this theme. * Please note that the function will not let you set insane values. * The allowable range is [8,64] */ - void setIconSize( int iconSize ); + void setIconSize( int iconSize ); - /** + /** * Enumerates the available view header policy options. * The returned descriptors are pairs in that the first item is the localized description * of the option value and the second item is the integer option value itself. */ - static QList< QPair< QString, int > > enumerateViewHeaderPolicyOptions(); + static QList< QPair< QString, int > > enumerateViewHeaderPolicyOptions(); protected: - /** + /** * Pure virtual reimplemented from OptionSet. */ - virtual void save( QDataStream &stream ) const; + virtual void save( QDataStream &stream ) const; - /** + /** * Pure virtual reimplemented from OptionSet. */ - virtual bool load( QDataStream &stream ); + virtual bool load( QDataStream &stream ); }; diff -Nru kdepim-4.12.97/messagelist/core/view.cpp kdepim-4.13.0/messagelist/core/view.cpp --- kdepim-4.12.97/messagelist/core/view.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/view.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -60,240 +60,240 @@ class View::Private { public: - Private( View *owner, Widget *parent ) - : q( owner ), mWidget( parent ), mModel( 0 ), mDelegate( new Delegate( owner ) ), - mAggregation( 0 ), mTheme( 0 ), mNeedToApplyThemeColumns( false ), - mLastCurrentItem( 0 ), mFirstShow( true ), mSaveThemeColumnStateOnSectionResize( true ), - mSaveThemeColumnStateTimer( 0 ), mApplyThemeColumnsTimer( 0 ), - mIgnoreUpdateGeometries( false ) { } - - void expandFullThread( const QModelIndex &index ); - - View * const q; - - Widget *mWidget; - Model *mModel; - Delegate *mDelegate; - - const Aggregation *mAggregation; ///< The Aggregation we're using now, shallow pointer - Theme *mTheme; ///< The Theme we're using now, shallow pointer - bool mNeedToApplyThemeColumns; ///< Flag signaling a pending application of theme columns - Item *mLastCurrentItem; - QPoint mMousePressPosition; - bool mFirstShow; - bool mSaveThemeColumnStateOnSectionResize; ///< This is used to filter out programmatic column resizes in slotSectionResized(). - QTimer * mSaveThemeColumnStateTimer; ///< Used to trigger a delayed "save theme state" - QTimer * mApplyThemeColumnsTimer; ///< Used to trigger a delayed "apply theme columns" - bool mIgnoreUpdateGeometries; ///< Shall we ignore the "update geometries" calls ? + Private( View *owner, Widget *parent ) + : q( owner ), mWidget( parent ), mModel( 0 ), mDelegate( new Delegate( owner ) ), + mAggregation( 0 ), mTheme( 0 ), mNeedToApplyThemeColumns( false ), + mLastCurrentItem( 0 ), mFirstShow( true ), mSaveThemeColumnStateOnSectionResize( true ), + mSaveThemeColumnStateTimer( 0 ), mApplyThemeColumnsTimer( 0 ), + mIgnoreUpdateGeometries( false ) { } + + void expandFullThread( const QModelIndex &index ); + + View * const q; + + Widget *mWidget; + Model *mModel; + Delegate *mDelegate; + + const Aggregation *mAggregation; ///< The Aggregation we're using now, shallow pointer + Theme *mTheme; ///< The Theme we're using now, shallow pointer + bool mNeedToApplyThemeColumns; ///< Flag signaling a pending application of theme columns + Item *mLastCurrentItem; + QPoint mMousePressPosition; + bool mFirstShow; + bool mSaveThemeColumnStateOnSectionResize; ///< This is used to filter out programmatic column resizes in slotSectionResized(). + QTimer * mSaveThemeColumnStateTimer; ///< Used to trigger a delayed "save theme state" + QTimer * mApplyThemeColumnsTimer; ///< Used to trigger a delayed "apply theme columns" + bool mIgnoreUpdateGeometries; ///< Shall we ignore the "update geometries" calls ? }; View::View( Widget *pParent ) - : QTreeView( pParent ), d( new Private( this, pParent ) ) + : QTreeView( pParent ), d( new Private( this, pParent ) ) { - d->mSaveThemeColumnStateTimer = new QTimer(); - connect( d->mSaveThemeColumnStateTimer, SIGNAL(timeout()), this, SLOT(saveThemeColumnState()) ); + d->mSaveThemeColumnStateTimer = new QTimer(); + connect( d->mSaveThemeColumnStateTimer, SIGNAL(timeout()), this, SLOT(saveThemeColumnState()) ); - d->mApplyThemeColumnsTimer = new QTimer(); - connect( d->mApplyThemeColumnsTimer, SIGNAL(timeout()), this, SLOT(applyThemeColumns()) ); + d->mApplyThemeColumnsTimer = new QTimer(); + connect( d->mApplyThemeColumnsTimer, SIGNAL(timeout()), this, SLOT(applyThemeColumns()) ); - setItemDelegate( d->mDelegate ); - setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); - setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn ); - setAlternatingRowColors( true ); - setAllColumnsShowFocus( true ); - setSelectionMode( QAbstractItemView::ExtendedSelection ); - viewport()->setAcceptDrops( true ); - - header()->setContextMenuPolicy( Qt::CustomContextMenu ); - connect( header(), SIGNAL(customContextMenuRequested(QPoint)), - SLOT(slotHeaderContextMenuRequested(QPoint)) ); - connect( header(), SIGNAL(sectionResized(int,int,int)), - SLOT(slotHeaderSectionResized(int,int,int)) ); - - header()->setClickable( true ); - header()->setResizeMode( QHeaderView::Interactive ); - header()->setMinimumSectionSize( 2 ); // QTreeView overrides our sections sizes if we set them smaller than this value - header()->setDefaultSectionSize( 2 ); // QTreeView overrides our sections sizes if we set them smaller than this value - - d->mModel = new Model( this ); - setModel( d->mModel ); - - connect( d->mModel, SIGNAL(statusMessage(QString)), - pParent, SIGNAL(statusMessage(QString)) ); - - //connect( selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), - // this, SLOT(slotCurrentIndexChanged(QModelIndex,QModelIndex)) ); - connect( selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection)), - Qt::UniqueConnection ); + setItemDelegate( d->mDelegate ); + setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); + setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn ); + setAlternatingRowColors( true ); + setAllColumnsShowFocus( true ); + setSelectionMode( QAbstractItemView::ExtendedSelection ); + viewport()->setAcceptDrops( true ); + + header()->setContextMenuPolicy( Qt::CustomContextMenu ); + connect( header(), SIGNAL(customContextMenuRequested(QPoint)), + SLOT(slotHeaderContextMenuRequested(QPoint)) ); + connect( header(), SIGNAL(sectionResized(int,int,int)), + SLOT(slotHeaderSectionResized(int,int,int)) ); + + header()->setClickable( true ); + header()->setResizeMode( QHeaderView::Interactive ); + header()->setMinimumSectionSize( 2 ); // QTreeView overrides our sections sizes if we set them smaller than this value + header()->setDefaultSectionSize( 2 ); // QTreeView overrides our sections sizes if we set them smaller than this value - // as in KDE3, when a root-item of a message thread is expanded, expand all children - connect( this, SIGNAL(expanded(QModelIndex)), this, SLOT(expandFullThread(QModelIndex)) ); + d->mModel = new Model( this ); + setModel( d->mModel ); + + connect( d->mModel, SIGNAL(statusMessage(QString)), + pParent, SIGNAL(statusMessage(QString)) ); + + //connect( selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), + // this, SLOT(slotCurrentIndexChanged(QModelIndex,QModelIndex)) ); + connect( selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection)), + Qt::UniqueConnection ); + + // as in KDE3, when a root-item of a message thread is expanded, expand all children + connect( this, SIGNAL(expanded(QModelIndex)), this, SLOT(expandFullThread(QModelIndex)) ); } View::~View() { - if ( d->mSaveThemeColumnStateTimer->isActive() ) - d->mSaveThemeColumnStateTimer->stop(); - delete d->mSaveThemeColumnStateTimer; - if ( d->mApplyThemeColumnsTimer->isActive() ) - d->mApplyThemeColumnsTimer->stop(); - delete d->mApplyThemeColumnsTimer; + if ( d->mSaveThemeColumnStateTimer->isActive() ) + d->mSaveThemeColumnStateTimer->stop(); + delete d->mSaveThemeColumnStateTimer; + if ( d->mApplyThemeColumnsTimer->isActive() ) + d->mApplyThemeColumnsTimer->stop(); + delete d->mApplyThemeColumnsTimer; - // Zero out the theme, aggregation and ApplyThemeColumnsTimer so Model will not cause accesses to them in its destruction process - d->mApplyThemeColumnsTimer = 0; + // Zero out the theme, aggregation and ApplyThemeColumnsTimer so Model will not cause accesses to them in its destruction process + d->mApplyThemeColumnsTimer = 0; - d->mTheme = 0; - d->mAggregation = 0; + d->mTheme = 0; + d->mAggregation = 0; - delete d; d = 0; + delete d; d = 0; } Model *View::model() const { - return d->mModel; + return d->mModel; } Delegate *View::delegate() const { - return d->mDelegate; + return d->mDelegate; } void View::ignoreCurrentChanges( bool ignore ) { - if ( ignore ) { - disconnect( selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection)) ); - viewport()->setUpdatesEnabled( false ); - } else { - connect( selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection)), - Qt::UniqueConnection ); - viewport()->setUpdatesEnabled( true ); - } + if ( ignore ) { + disconnect( selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection)) ); + viewport()->setUpdatesEnabled( false ); + } else { + connect( selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection)), + Qt::UniqueConnection ); + viewport()->setUpdatesEnabled( true ); + } } void View::ignoreUpdateGeometries( bool ignore ) { - d->mIgnoreUpdateGeometries = ignore; + d->mIgnoreUpdateGeometries = ignore; } bool View::isScrollingLocked() const { - // There is another popular requisite: people want the view to automatically - // scroll in order to show new arriving mail. This actually makes sense - // only when the view is sorted by date and the new mail is (usually) either - // appended at the bottom or inserted at the top. It would be also confusing - // when the user is browsing some other thread in the meantime. - // - // So here we make a simple guess: if the view is scrolled somewhere in the - // middle then we assume that the user is browsing other threads and we - // try to keep the currently selected item steady on the screen. - // When the view is "locked" to the top (scrollbar value 0) or to the - // bottom (scrollbar value == maximum) then we assume that the user - // isn't browsing and we should attempt to show the incoming messages - // by keeping the view "locked". - // - // The "locking" also doesn't make sense in the first big fill view job. - // [Well this concept is pre-akonadi. Now the loading is all async anyway... - // So all this code is actually triggered during the initial loading, too.] - const int scrollBarPosition = verticalScrollBar()->value(); - const int scrollBarMaximum = verticalScrollBar()->maximum(); - const SortOrder* sortOrder = d->mModel->sortOrder(); - const bool lockView = ( - // not the first loading job - !d->mModel->isLoading() - ) && ( - // messages sorted by date - ( sortOrder->messageSorting() == SortOrder::SortMessagesByDateTime ) || - ( sortOrder->messageSorting() == SortOrder::SortMessagesByDateTimeOfMostRecent ) - ) && ( - // scrollbar at top (Descending order) or bottom (Ascending order) - ( scrollBarPosition == 0 && sortOrder->messageSortDirection() == SortOrder::Descending ) || - ( scrollBarPosition == scrollBarMaximum && sortOrder->messageSortDirection() == SortOrder::Ascending ) - ); - return lockView; + // There is another popular requisite: people want the view to automatically + // scroll in order to show new arriving mail. This actually makes sense + // only when the view is sorted by date and the new mail is (usually) either + // appended at the bottom or inserted at the top. It would be also confusing + // when the user is browsing some other thread in the meantime. + // + // So here we make a simple guess: if the view is scrolled somewhere in the + // middle then we assume that the user is browsing other threads and we + // try to keep the currently selected item steady on the screen. + // When the view is "locked" to the top (scrollbar value 0) or to the + // bottom (scrollbar value == maximum) then we assume that the user + // isn't browsing and we should attempt to show the incoming messages + // by keeping the view "locked". + // + // The "locking" also doesn't make sense in the first big fill view job. + // [Well this concept is pre-akonadi. Now the loading is all async anyway... + // So all this code is actually triggered during the initial loading, too.] + const int scrollBarPosition = verticalScrollBar()->value(); + const int scrollBarMaximum = verticalScrollBar()->maximum(); + const SortOrder* sortOrder = d->mModel->sortOrder(); + const bool lockView = ( + // not the first loading job + !d->mModel->isLoading() + ) && ( + // messages sorted by date + ( sortOrder->messageSorting() == SortOrder::SortMessagesByDateTime ) || + ( sortOrder->messageSorting() == SortOrder::SortMessagesByDateTimeOfMostRecent ) + ) && ( + // scrollbar at top (Descending order) or bottom (Ascending order) + ( scrollBarPosition == 0 && sortOrder->messageSortDirection() == SortOrder::Descending ) || + ( scrollBarPosition == scrollBarMaximum && sortOrder->messageSortDirection() == SortOrder::Ascending ) + ); + return lockView; } void View::updateGeometries() { - if( d->mIgnoreUpdateGeometries || !d->mModel ) - return; + if( d->mIgnoreUpdateGeometries || !d->mModel ) + return; - const int scrollBarPositionBefore = verticalScrollBar()->value(); - const bool lockView = isScrollingLocked(); + const int scrollBarPositionBefore = verticalScrollBar()->value(); + const bool lockView = isScrollingLocked(); - QTreeView::updateGeometries(); + QTreeView::updateGeometries(); - if ( lockView ) - { - // we prefer to keep the view locked to the top or bottom - if ( scrollBarPositionBefore != 0 ) - { - // we wanted the view to be locked to the bottom - if ( verticalScrollBar()->value() != verticalScrollBar()->maximum() ) - verticalScrollBar()->setValue( verticalScrollBar()->maximum() ); - } // else we wanted the view to be locked to top and we shouldn't need to do anything - } + if ( lockView ) + { + // we prefer to keep the view locked to the top or bottom + if ( scrollBarPositionBefore != 0 ) + { + // we wanted the view to be locked to the bottom + if ( verticalScrollBar()->value() != verticalScrollBar()->maximum() ) + verticalScrollBar()->setValue( verticalScrollBar()->maximum() ); + } // else we wanted the view to be locked to top and we shouldn't need to do anything + } } StorageModel * View::storageModel() const { - return d->mModel->storageModel(); + return d->mModel->storageModel(); } void View::setAggregation( const Aggregation * aggregation ) { - d->mAggregation = aggregation; - d->mModel->setAggregation( aggregation ); + d->mAggregation = aggregation; + d->mModel->setAggregation( aggregation ); - // use uniform row heights to speed up, but only if there are no group headers used - setUniformRowHeights( d->mAggregation->grouping() == Aggregation::NoGrouping ); + // use uniform row heights to speed up, but only if there are no group headers used + setUniformRowHeights( d->mAggregation->grouping() == Aggregation::NoGrouping ); } void View::setTheme( Theme * theme ) { - d->mNeedToApplyThemeColumns = true; - d->mTheme = theme; - d->mDelegate->setTheme( theme ); - d->mModel->setTheme( theme ); + d->mNeedToApplyThemeColumns = true; + d->mTheme = theme; + d->mDelegate->setTheme( theme ); + d->mModel->setTheme( theme ); } void View::setSortOrder( const SortOrder * sortOrder ) { - d->mModel->setSortOrder( sortOrder ); + d->mModel->setSortOrder( sortOrder ); } void View::reload() { - setStorageModel( storageModel() ); + setStorageModel( storageModel() ); } void View::setStorageModel( StorageModel * storageModel, PreSelectionMode preSelectionMode ) { - // This will cause the model to be reset. - d->mSaveThemeColumnStateOnSectionResize = false; - d->mModel->setStorageModel( storageModel, preSelectionMode ); - d->mSaveThemeColumnStateOnSectionResize = true; + // This will cause the model to be reset. + d->mSaveThemeColumnStateOnSectionResize = false; + d->mModel->setStorageModel( storageModel, preSelectionMode ); + d->mSaveThemeColumnStateOnSectionResize = true; } void View::modelJobBatchStarted() { - // This is called by the model when the first job of a batch starts - d->mWidget->viewJobBatchStarted(); + // This is called by the model when the first job of a batch starts + d->mWidget->viewJobBatchStarted(); } void View::modelJobBatchTerminated() { - // This is called by the model when all the pending jobs have been processed - d->mWidget->viewJobBatchTerminated(); + // This is called by the model when all the pending jobs have been processed + d->mWidget->viewJobBatchTerminated(); } void View::modelHasBeenReset() { - // This is called by Model when it has been reset. - if ( d && d->mNeedToApplyThemeColumns ) - applyThemeColumns(); + // This is called by Model when it has been reset. + if ( d && d->mNeedToApplyThemeColumns ) + applyThemeColumns(); } ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -325,421 +325,421 @@ void View::applyThemeColumns() { - if ( !d->mApplyThemeColumnsTimer ) { - return; - } - - if ( d->mApplyThemeColumnsTimer->isActive() ) - d->mApplyThemeColumnsTimer->stop(); - - if ( !d->mTheme ) - return; - - //kDebug() << "Apply theme columns"; - - - const QList< Theme::Column * > & columns = d->mTheme->columns(); - - if ( columns.isEmpty() ) - return; // bad theme - - if ( !viewport()->isVisible() ) - return; // invisible - - if ( viewport()->width() < 1 ) - return; // insane width - - // Now we want to distribute the available width on all the visible columns. - // - // The rules: - // - The visible columns will span the width of the view, if possible. - // - The columns with a saved width should take that width. - // - The columns on the left should take more space, if possible. - // - The columns with no text take just slightly more than their size hint. - // while the columns with text take possibly a lot more. - // - - // Note that the first column is always shown (it can't be hidden at all) - - // The algorithm below is a sort of compromise between: - // - Saving the user preferences for widths - // - Using exactly the available view space - // - // It "tends to work" in all cases: - // - When there are no user preferences saved and the column widths must be - // automatically computed to make best use of available space - // - When there are user preferences for only some of the columns - // and that should be somewhat preserved while still using all the - // available space. - // - When all the columns have well defined saved widths - - QList< Theme::Column * >::ConstIterator it; - int idx = 0; - - // Gather total size "hint" for visible sections: if the widths of the columns wers - // all saved then the total hint is equal to the total saved width. - - int totalVisibleWidthHint = 0; - QList< int > lColumnSizeHints; - QList< Theme::Column * >::ConstIterator end( columns.end() ); - - for ( it = columns.constBegin(); it != end; ++it ) - { - if ( ( *it )->currentlyVisible() || ( idx == 0 ) ) - { - //kDebug() << "Column " << idx << " will be visible"; - // Column visible - const int savedWidth = ( *it )->currentWidth(); - const int hintWidth = d->mDelegate->sizeHintForItemTypeAndColumn( Item::Message, idx ).width(); - totalVisibleWidthHint += savedWidth > 0 ? savedWidth : hintWidth; - lColumnSizeHints.append( hintWidth ); - //kDebug() << "Column " << idx << " size hint is " << hintWidth; - } else { - //kDebug() << "Column " << idx << " will be not visible"; - // The column is not visible - lColumnSizeHints.append( -1 ); // dummy - } - idx++; - } - - if ( totalVisibleWidthHint < 16 ) - totalVisibleWidthHint = 16; // be reasonable - - // Now compute somewhat "proportional" widths. - idx = 0; - - QList< int > lColumnWidths; - int totalVisibleWidth = 0; - end = columns.constEnd(); - for ( it = columns.constBegin(); it != end; ++it ) - { - int savedWidth = ( *it )->currentWidth(); - int hintWidth = savedWidth > 0 ? savedWidth : lColumnSizeHints[ idx ]; - int realWidth; - - if ( ( *it )->currentlyVisible() || ( idx == 0 ) ) - { - if ( ( *it )->containsTextItems() ) - { - // the column contains text items, it should get more space (if possible) - realWidth = ( ( hintWidth * viewport()->width() ) / totalVisibleWidthHint ); - } else { - // the column contains no text items, it should get exactly its hint/saved width. - realWidth = hintWidth; - } + if ( !d->mApplyThemeColumnsTimer ) { + return; + } - if ( realWidth < 2 ) - realWidth = 2; // don't allow very insane values + if ( d->mApplyThemeColumnsTimer->isActive() ) + d->mApplyThemeColumnsTimer->stop(); - totalVisibleWidth += realWidth; - } else { - // Column not visible - realWidth = -1; + if ( !d->mTheme ) + return; + + //kDebug() << "Apply theme columns"; + + + const QList< Theme::Column * > & columns = d->mTheme->columns(); + + if ( columns.isEmpty() ) + return; // bad theme + + if ( !viewport()->isVisible() ) + return; // invisible + + if ( viewport()->width() < 1 ) + return; // insane width + + // Now we want to distribute the available width on all the visible columns. + // + // The rules: + // - The visible columns will span the width of the view, if possible. + // - The columns with a saved width should take that width. + // - The columns on the left should take more space, if possible. + // - The columns with no text take just slightly more than their size hint. + // while the columns with text take possibly a lot more. + // + + // Note that the first column is always shown (it can't be hidden at all) + + // The algorithm below is a sort of compromise between: + // - Saving the user preferences for widths + // - Using exactly the available view space + // + // It "tends to work" in all cases: + // - When there are no user preferences saved and the column widths must be + // automatically computed to make best use of available space + // - When there are user preferences for only some of the columns + // and that should be somewhat preserved while still using all the + // available space. + // - When all the columns have well defined saved widths + + QList< Theme::Column * >::ConstIterator it; + int idx = 0; + + // Gather total size "hint" for visible sections: if the widths of the columns wers + // all saved then the total hint is equal to the total saved width. + + int totalVisibleWidthHint = 0; + QList< int > lColumnSizeHints; + QList< Theme::Column * >::ConstIterator end( columns.end() ); + + for ( it = columns.constBegin(); it != end; ++it ) + { + if ( ( *it )->currentlyVisible() || ( idx == 0 ) ) + { + //kDebug() << "Column " << idx << " will be visible"; + // Column visible + const int savedWidth = ( *it )->currentWidth(); + const int hintWidth = d->mDelegate->sizeHintForItemTypeAndColumn( Item::Message, idx ).width(); + totalVisibleWidthHint += savedWidth > 0 ? savedWidth : hintWidth; + lColumnSizeHints.append( hintWidth ); + //kDebug() << "Column " << idx << " size hint is " << hintWidth; + } else { + //kDebug() << "Column " << idx << " will be not visible"; + // The column is not visible + lColumnSizeHints.append( -1 ); // dummy + } + idx++; } - lColumnWidths.append( realWidth ); + if ( totalVisibleWidthHint < 16 ) + totalVisibleWidthHint = 16; // be reasonable + + // Now compute somewhat "proportional" widths. + idx = 0; + + QList< int > lColumnWidths; + int totalVisibleWidth = 0; + end = columns.constEnd(); + for ( it = columns.constBegin(); it != end; ++it ) + { + int savedWidth = ( *it )->currentWidth(); + int hintWidth = savedWidth > 0 ? savedWidth : lColumnSizeHints[ idx ]; + int realWidth; - idx++; - } + if ( ( *it )->currentlyVisible() || ( idx == 0 ) ) + { + if ( ( *it )->containsTextItems() ) + { + // the column contains text items, it should get more space (if possible) + realWidth = ( ( hintWidth * viewport()->width() ) / totalVisibleWidthHint ); + } else { + // the column contains no text items, it should get exactly its hint/saved width. + realWidth = hintWidth; + } - // Now the algorithm above may be wrong for several reasons... - // - We're using fixed widths for certain columns and proportional - // for others... - // - The user might have changed the width of the view from the - // time in that the widths have been saved - // - There are some (not well identified) issues with the QTreeView - // scrollbar that make our view appear larger or shorter by 2-3 pixels - // sometimes. - // - ... - // So we correct the previous estimates by trying to use exactly - // the available space. - - idx = 0; - - if ( totalVisibleWidth != viewport()->width() ) - { - // The estimated widths were not using exactly the available space. - if ( totalVisibleWidth < viewport()->width() ) - { - // We were using less space than available. - - // Give the additional space to the text columns - // also give more space to the first ones and less space to the last ones - int available = viewport()->width() - totalVisibleWidth; - - end = columns.end(); - for ( it = columns.begin(); it != end; ++it ) - { - if ( ( ( *it )->currentlyVisible() || ( idx == 0 ) ) && ( *it )->containsTextItems() ) - { - // give more space to this column - available >>= 1; // eat half of the available space - lColumnWidths[ idx ] += available; // and give it to this column - if ( available < 1 ) - break; // no more space to give away + if ( realWidth < 2 ) + realWidth = 2; // don't allow very insane values + + totalVisibleWidth += realWidth; + } else { + // Column not visible + realWidth = -1; } + lColumnWidths.append( realWidth ); + idx++; - } + } - // if any space is still available, give it to the first column - if ( available ) - lColumnWidths[ 0 ] += available; - } else { - // We were using more space than available + // Now the algorithm above may be wrong for several reasons... + // - We're using fixed widths for certain columns and proportional + // for others... + // - The user might have changed the width of the view from the + // time in that the widths have been saved + // - There are some (not well identified) issues with the QTreeView + // scrollbar that make our view appear larger or shorter by 2-3 pixels + // sometimes. + // - ... + // So we correct the previous estimates by trying to use exactly + // the available space. - // If the columns span just a little bit more than the view then - // try to squeeze them in order to make them fit - if ( totalVisibleWidth < ( viewport()->width() + 100 ) ) - { - int missing = totalVisibleWidth - viewport()->width(); - int count = lColumnWidths.count(); - - if ( missing > 0 ) - { - idx = count - 1; - - while ( idx >= 0 ) - { - if ( columns.at( idx )->currentlyVisible() || ( idx == 0 ) ) - { - int chop = lColumnWidths[ idx ] - lColumnSizeHints[ idx ]; - if ( chop > 0 ) - { - if ( chop > missing ) - chop = missing; - lColumnWidths[ idx ] -= chop; - missing -= chop; - if ( missing < 1 ) - break; // no more space to recover - } - } // else it's invisible - idx--; - } - } - } - } - } - - // We're ready to assign widths. - - bool oldSave = d->mSaveThemeColumnStateOnSectionResize; - d->mSaveThemeColumnStateOnSectionResize = false; - - // A huge problem here is that QHeaderView goes quite nuts if we show or hide sections - // while resizing them. This is because it has several machineries aimed to delay - // the layout to the last possible moment. So if we show a column, it will tend to - // screw up the layout of other ones. - - // We first loop showing/hiding columns then. - - idx = 0; - - //kDebug() << "Entering column show/hide loop"; - - end = columns.constEnd(); - for ( it = columns.constBegin(); it != end; ++it ) - { - bool visible = ( idx == 0 ) || ( *it )->currentlyVisible(); - //kDebug() << "Column " << idx << " visible " << visible; - ( *it )->setCurrentlyVisible( visible ); - header()->setSectionHidden( idx, !visible ); - idx++; - } - - // Then we loop assigning widths. This is still complicated since QHeaderView tries - // very badly to stretch the last section and thus will resize it in the meantime. - // But seems to work most of the times... - - idx = 0; - - end = columns.constEnd(); - for ( it = columns.constBegin(); it != end; ++it ) - { - if ( ( *it )->currentlyVisible() ) - { - //kDebug() << "Resize section " << idx << " to " << lColumnWidths[ idx ]; - const int columnWidth( lColumnWidths[ idx ] ); - ( *it )->setCurrentWidth( columnWidth ); - header()->resizeSection( idx, columnWidth ); - } else { - ( *it )->setCurrentWidth( -1 ); + idx = 0; + + if ( totalVisibleWidth != viewport()->width() ) + { + // The estimated widths were not using exactly the available space. + if ( totalVisibleWidth < viewport()->width() ) + { + // We were using less space than available. + + // Give the additional space to the text columns + // also give more space to the first ones and less space to the last ones + int available = viewport()->width() - totalVisibleWidth; + + end = columns.end(); + for ( it = columns.begin(); it != end; ++it ) + { + if ( ( ( *it )->currentlyVisible() || ( idx == 0 ) ) && ( *it )->containsTextItems() ) + { + // give more space to this column + available >>= 1; // eat half of the available space + lColumnWidths[ idx ] += available; // and give it to this column + if ( available < 1 ) + break; // no more space to give away + } + + idx++; + } + + // if any space is still available, give it to the first column + if ( available ) + lColumnWidths[ 0 ] += available; + } else { + // We were using more space than available + + // If the columns span just a little bit more than the view then + // try to squeeze them in order to make them fit + if ( totalVisibleWidth < ( viewport()->width() + 100 ) ) + { + int missing = totalVisibleWidth - viewport()->width(); + int count = lColumnWidths.count(); + + if ( missing > 0 ) + { + idx = count - 1; + + while ( idx >= 0 ) + { + if ( columns.at( idx )->currentlyVisible() || ( idx == 0 ) ) + { + int chop = lColumnWidths[ idx ] - lColumnSizeHints[ idx ]; + if ( chop > 0 ) + { + if ( chop > missing ) + chop = missing; + lColumnWidths[ idx ] -= chop; + missing -= chop; + if ( missing < 1 ) + break; // no more space to recover + } + } // else it's invisible + idx--; + } + } + } + } } - idx++; - } - idx = 0; + // We're ready to assign widths. + + bool oldSave = d->mSaveThemeColumnStateOnSectionResize; + d->mSaveThemeColumnStateOnSectionResize = false; + + // A huge problem here is that QHeaderView goes quite nuts if we show or hide sections + // while resizing them. This is because it has several machineries aimed to delay + // the layout to the last possible moment. So if we show a column, it will tend to + // screw up the layout of other ones. - bool bTriggeredQtBug = false; - end = columns.constEnd(); - for ( it = columns.constBegin(); it != end; ++it ) - { - if ( !header()->isSectionHidden( idx ) ) + // We first loop showing/hiding columns then. + + idx = 0; + + //kDebug() << "Entering column show/hide loop"; + + end = columns.constEnd(); + for ( it = columns.constBegin(); it != end; ++it ) { - if ( !( *it )->currentlyVisible() ) - { - bTriggeredQtBug = true; - } + bool visible = ( idx == 0 ) || ( *it )->currentlyVisible(); + //kDebug() << "Column " << idx << " visible " << visible; + ( *it )->setCurrentlyVisible( visible ); + header()->setSectionHidden( idx, !visible ); + idx++; } - idx++; - } - setHeaderHidden( d->mTheme->viewHeaderPolicy() == Theme::NeverShowHeader ); + // Then we loop assigning widths. This is still complicated since QHeaderView tries + // very badly to stretch the last section and thus will resize it in the meantime. + // But seems to work most of the times... - d->mSaveThemeColumnStateOnSectionResize = oldSave; - d->mNeedToApplyThemeColumns = false; + idx = 0; - static bool bAllowRecursion = true; + end = columns.constEnd(); + for ( it = columns.constBegin(); it != end; ++it ) + { + if ( ( *it )->currentlyVisible() ) + { + //kDebug() << "Resize section " << idx << " to " << lColumnWidths[ idx ]; + const int columnWidth( lColumnWidths[ idx ] ); + ( *it )->setCurrentWidth( columnWidth ); + header()->resizeSection( idx, columnWidth ); + } else { + ( *it )->setCurrentWidth( -1 ); + } + idx++; + } - if (bTriggeredQtBug && bAllowRecursion) - { - bAllowRecursion = false; - //kDebug() << "I've triggered the QHeaderView bug: trying to fix by calling myself again"; - applyThemeColumns(); - bAllowRecursion = true; - } + idx = 0; + + bool bTriggeredQtBug = false; + end = columns.constEnd(); + for ( it = columns.constBegin(); it != end; ++it ) + { + if ( !header()->isSectionHidden( idx ) ) + { + if ( !( *it )->currentlyVisible() ) + { + bTriggeredQtBug = true; + } + } + idx++; + } + + setHeaderHidden( d->mTheme->viewHeaderPolicy() == Theme::NeverShowHeader ); + + d->mSaveThemeColumnStateOnSectionResize = oldSave; + d->mNeedToApplyThemeColumns = false; + + static bool bAllowRecursion = true; + + if (bTriggeredQtBug && bAllowRecursion) + { + bAllowRecursion = false; + //kDebug() << "I've triggered the QHeaderView bug: trying to fix by calling myself again"; + applyThemeColumns(); + bAllowRecursion = true; + } } void View::triggerDelayedApplyThemeColumns() { - if ( d->mApplyThemeColumnsTimer->isActive() ) - d->mApplyThemeColumnsTimer->stop(); - d->mApplyThemeColumnsTimer->setSingleShot( true ); - d->mApplyThemeColumnsTimer->start( 100 ); + if ( d->mApplyThemeColumnsTimer->isActive() ) + d->mApplyThemeColumnsTimer->stop(); + d->mApplyThemeColumnsTimer->setSingleShot( true ); + d->mApplyThemeColumnsTimer->start( 100 ); } void View::saveThemeColumnState() { - if ( d->mSaveThemeColumnStateTimer->isActive() ) - d->mSaveThemeColumnStateTimer->stop(); + if ( d->mSaveThemeColumnStateTimer->isActive() ) + d->mSaveThemeColumnStateTimer->stop(); - if ( !d->mTheme ) - return; + if ( !d->mTheme ) + return; - if ( d->mNeedToApplyThemeColumns ) - return; // don't save the state if it hasn't been applied at all + if ( d->mNeedToApplyThemeColumns ) + return; // don't save the state if it hasn't been applied at all - //kDebug() << "Save theme column state"; + //kDebug() << "Save theme column state"; - const QList< Theme::Column * > & columns = d->mTheme->columns(); + const QList< Theme::Column * > & columns = d->mTheme->columns(); - if ( columns.isEmpty() ) - return; // bad theme + if ( columns.isEmpty() ) + return; // bad theme - int idx = 0; + int idx = 0; - QList< Theme::Column * >::ConstIterator end(columns.constEnd()); - for ( QList< Theme::Column * >::ConstIterator it = columns.constBegin(); it != end; ++it ) - { - if ( header()->isSectionHidden( idx ) ) + QList< Theme::Column * >::ConstIterator end(columns.constEnd()); + for ( QList< Theme::Column * >::ConstIterator it = columns.constBegin(); it != end; ++it ) { - //kDebug() << "Section " << idx << " is hidden"; - ( *it )->setCurrentlyVisible( false ); - ( *it )->setCurrentWidth( -1 ); // reset (hmmm... we could use the "don't touch" policy here too...) - } else { - //kDebug() << "Section " << idx << " is visible and has size " << header()->sectionSize( idx ); - ( *it )->setCurrentlyVisible( true ); - ( *it )->setCurrentWidth( header()->sectionSize( idx ) ); + if ( header()->isSectionHidden( idx ) ) + { + //kDebug() << "Section " << idx << " is hidden"; + ( *it )->setCurrentlyVisible( false ); + ( *it )->setCurrentWidth( -1 ); // reset (hmmm... we could use the "don't touch" policy here too...) + } else { + //kDebug() << "Section " << idx << " is visible and has size " << header()->sectionSize( idx ); + ( *it )->setCurrentlyVisible( true ); + ( *it )->setCurrentWidth( header()->sectionSize( idx ) ); + } + idx++; } - idx++; - } } void View::triggerDelayedSaveThemeColumnState() { - if ( d->mSaveThemeColumnStateTimer->isActive() ) - d->mSaveThemeColumnStateTimer->stop(); - d->mSaveThemeColumnStateTimer->setSingleShot( true ); - d->mSaveThemeColumnStateTimer->start( 200 ); + if ( d->mSaveThemeColumnStateTimer->isActive() ) + d->mSaveThemeColumnStateTimer->stop(); + d->mSaveThemeColumnStateTimer->setSingleShot( true ); + d->mSaveThemeColumnStateTimer->start( 200 ); } void View::resizeEvent( QResizeEvent * e ) { - kDebug() << "Resize event enter (viewport width is " << viewport()->width() << ")"; + kDebug() << "Resize event enter (viewport width is " << viewport()->width() << ")"; - QTreeView::resizeEvent( e ); + QTreeView::resizeEvent( e ); - if ( !isVisible() ) - return; // don't play with + if ( !isVisible() ) + return; // don't play with - if ( (!d->mFirstShow) && d->mNeedToApplyThemeColumns ) - triggerDelayedApplyThemeColumns(); + if ( (!d->mFirstShow) && d->mNeedToApplyThemeColumns ) + triggerDelayedApplyThemeColumns(); - if ( header()->isVisible() ) - return; + if ( header()->isVisible() ) + return; - // header invisible + // header invisible - bool oldSave = d->mSaveThemeColumnStateOnSectionResize; - d->mSaveThemeColumnStateOnSectionResize = false; + bool oldSave = d->mSaveThemeColumnStateOnSectionResize; + d->mSaveThemeColumnStateOnSectionResize = false; - const int count = header()->count(); - if ( ( count - header()->hiddenSectionCount() ) < 2 ) - { - // a single column visible: resize it - int visibleIndex; - for ( visibleIndex = 0; visibleIndex < count; visibleIndex++ ) + const int count = header()->count(); + if ( ( count - header()->hiddenSectionCount() ) < 2 ) { - if ( !header()->isSectionHidden( visibleIndex ) ) - break; + // a single column visible: resize it + int visibleIndex; + for ( visibleIndex = 0; visibleIndex < count; visibleIndex++ ) + { + if ( !header()->isSectionHidden( visibleIndex ) ) + break; + } + if ( visibleIndex < count ) + header()->resizeSection( visibleIndex, viewport()->width() - 4 ); } - if ( visibleIndex < count ) - header()->resizeSection( visibleIndex, viewport()->width() - 4 ); - } - d->mSaveThemeColumnStateOnSectionResize = oldSave; + d->mSaveThemeColumnStateOnSectionResize = oldSave; - triggerDelayedSaveThemeColumnState(); + triggerDelayedSaveThemeColumnState(); } void View::modelAboutToEmitLayoutChanged() { - // QHeaderView goes totally NUTS with a layoutChanged() call - d->mSaveThemeColumnStateOnSectionResize = false; + // QHeaderView goes totally NUTS with a layoutChanged() call + d->mSaveThemeColumnStateOnSectionResize = false; } void View::modelEmittedLayoutChanged() { - // This is after a first chunk of work has been done by the model: do apply column states - d->mSaveThemeColumnStateOnSectionResize = true; - applyThemeColumns(); + // This is after a first chunk of work has been done by the model: do apply column states + d->mSaveThemeColumnStateOnSectionResize = true; + applyThemeColumns(); } void View::slotHeaderSectionResized( int logicalIndex, int oldWidth, int newWidth ) { - Q_UNUSED( logicalIndex ); - Q_UNUSED( oldWidth ); - Q_UNUSED( newWidth ); + Q_UNUSED( logicalIndex ); + Q_UNUSED( oldWidth ); + Q_UNUSED( newWidth ); - if ( d->mSaveThemeColumnStateOnSectionResize ) - triggerDelayedSaveThemeColumnState(); + if ( d->mSaveThemeColumnStateOnSectionResize ) + triggerDelayedSaveThemeColumnState(); } int View::sizeHintForColumn( int logicalColumnIndex ) const { - // QTreeView: please don't touch my column widths... - int w = header()->sectionSize( logicalColumnIndex ); - if ( w > 0 ) + // QTreeView: please don't touch my column widths... + int w = header()->sectionSize( logicalColumnIndex ); + if ( w > 0 ) + return w; + if ( !d->mDelegate ) + return 32; // dummy + w = d->mDelegate->sizeHintForItemTypeAndColumn( Item::Message, logicalColumnIndex ).width(); return w; - if ( !d->mDelegate ) - return 32; // dummy - w = d->mDelegate->sizeHintForItemTypeAndColumn( Item::Message, logicalColumnIndex ).width(); - return w; } void View::showEvent( QShowEvent *e ) { - QTreeView::showEvent( e ); - if ( d->mFirstShow ) - { - // If we're shown for the first time and the theme has been already set - // then we need to reapply the theme column widths since the previous - // application probably used invalid widths. - // - if ( d->mTheme ) - triggerDelayedApplyThemeColumns(); - d->mFirstShow = false; - } + QTreeView::showEvent( e ); + if ( d->mFirstShow ) + { + // If we're shown for the first time and the theme has been already set + // then we need to reapply the theme column widths since the previous + // application probably used invalid widths. + // + if ( d->mTheme ) + triggerDelayedApplyThemeColumns(); + d->mFirstShow = false; + } } const int gHeaderContextMenuAdjustColumnSizesId = -1; @@ -748,2027 +748,2027 @@ void View::slotHeaderContextMenuRequested( const QPoint &pnt ) { - if ( !d->mTheme ) - return; + if ( !d->mTheme ) + return; - const QList< Theme::Column * > & columns = d->mTheme->columns(); + const QList< Theme::Column * > & columns = d->mTheme->columns(); - if ( columns.isEmpty() ) - return; // bad theme + if ( columns.isEmpty() ) + return; // bad theme - // the menu for the columns - KMenu menu; - - QSignalMapper *showColumnSignalMapper = new QSignalMapper( &menu ); - int idx = 0; - QList< Theme::Column * >::ConstIterator end(columns.end()); - for ( QList< Theme::Column * >::ConstIterator it = columns.begin(); it != end; ++it ) - { - QAction *act = menu.addAction( ( *it )->label() ); - act->setCheckable( true ); - act->setChecked( !header()->isSectionHidden( idx ) ); - if ( idx == 0 ) - act->setEnabled( false ); - QObject::connect( act, SIGNAL(triggered()), showColumnSignalMapper, SLOT(map()) ); - showColumnSignalMapper->setMapping( act, idx ); - - idx++; - } - QObject::connect( showColumnSignalMapper, SIGNAL(mapped(int)), this, SLOT(slotShowHideColumn(int)) ); - - menu.addSeparator(); - { - QAction *act = menu.addAction( i18n( "Adjust Column Sizes" ) ); - QObject::connect( act, SIGNAL(triggered()), this, SLOT(slotAdjustColumnSizes()) ); - } - { - QAction *act = menu.addAction( i18n( "Show Default Columns" ) ); - QObject::connect( act, SIGNAL(triggered()), this, SLOT(slotShowDefaultColumns()) ); - } - menu.addSeparator(); - { - QAction *act = menu.addAction( i18n( "Display Tooltips" ) ); - act->setCheckable( true ); - act->setChecked( Settings::self()->messageToolTipEnabled() ); - QObject::connect( act, SIGNAL(triggered(bool)), this, SLOT(slotDisplayTooltips(bool)) ); - } - menu.addSeparator(); + // the menu for the columns + KMenu menu; + + QSignalMapper *showColumnSignalMapper = new QSignalMapper( &menu ); + int idx = 0; + QList< Theme::Column * >::ConstIterator end(columns.end()); + for ( QList< Theme::Column * >::ConstIterator it = columns.begin(); it != end; ++it ) + { + QAction *act = menu.addAction( ( *it )->label() ); + act->setCheckable( true ); + act->setChecked( !header()->isSectionHidden( idx ) ); + if ( idx == 0 ) + act->setEnabled( false ); + QObject::connect( act, SIGNAL(triggered()), showColumnSignalMapper, SLOT(map()) ); + showColumnSignalMapper->setMapping( act, idx ); - MessageList::Util::fillViewMenu( &menu, d->mWidget ); + idx++; + } + QObject::connect( showColumnSignalMapper, SIGNAL(mapped(int)), this, SLOT(slotShowHideColumn(int)) ); - menu.exec( header()->mapToGlobal( pnt ) ); + menu.addSeparator(); + { + QAction *act = menu.addAction( i18n( "Adjust Column Sizes" ) ); + QObject::connect( act, SIGNAL(triggered()), this, SLOT(slotAdjustColumnSizes()) ); + } + { + QAction *act = menu.addAction( i18n( "Show Default Columns" ) ); + QObject::connect( act, SIGNAL(triggered()), this, SLOT(slotShowDefaultColumns()) ); + } + menu.addSeparator(); + { + QAction *act = menu.addAction( i18n( "Display Tooltips" ) ); + act->setCheckable( true ); + act->setChecked( Settings::self()->messageToolTipEnabled() ); + QObject::connect( act, SIGNAL(triggered(bool)), this, SLOT(slotDisplayTooltips(bool)) ); + } + menu.addSeparator(); + + MessageList::Util::fillViewMenu( &menu, d->mWidget ); + + menu.exec( header()->mapToGlobal( pnt ) ); } void View::slotAdjustColumnSizes() { - if ( !d->mTheme ) - return; + if ( !d->mTheme ) + return; - d->mTheme->resetColumnSizes(); - applyThemeColumns(); + d->mTheme->resetColumnSizes(); + applyThemeColumns(); } void View::slotShowDefaultColumns() { - if ( !d->mTheme ) - return; + if ( !d->mTheme ) + return; - d->mTheme->resetColumnState(); - applyThemeColumns(); + d->mTheme->resetColumnState(); + applyThemeColumns(); } void View::slotDisplayTooltips( bool showTooltips ) { - Settings::self()->setMessageToolTipEnabled( showTooltips ); + Settings::self()->setMessageToolTipEnabled( showTooltips ); } void View::slotShowHideColumn( int columnIdx ) { - if ( !d->mTheme ) - return; // oops + if ( !d->mTheme ) + return; // oops - if ( columnIdx == 0 ) - return; // can never be hidden + if ( columnIdx == 0 ) + return; // can never be hidden - if ( columnIdx >= d->mTheme->columns().count() ) - return; + if ( columnIdx >= d->mTheme->columns().count() ) + return; - const bool showIt = header()->isSectionHidden( columnIdx ); + const bool showIt = header()->isSectionHidden( columnIdx ); - Theme::Column * column = d->mTheme->columns().at( columnIdx ); - Q_ASSERT( column ); + Theme::Column * column = d->mTheme->columns().at( columnIdx ); + Q_ASSERT( column ); - // first save column state (as it is, with the column still in previous state) - saveThemeColumnState(); + // first save column state (as it is, with the column still in previous state) + saveThemeColumnState(); - // If a section has just been shown, invalidate its width in the skin - // since QTreeView assigned it a (possibly insane) default width. - // If a section has been hidden, then invalidate its width anyway... - // so finally invalidate width always, here. - column->setCurrentlyVisible( showIt ); - column->setCurrentWidth( -1 ); + // If a section has just been shown, invalidate its width in the skin + // since QTreeView assigned it a (possibly insane) default width. + // If a section has been hidden, then invalidate its width anyway... + // so finally invalidate width always, here. + column->setCurrentlyVisible( showIt ); + column->setCurrentWidth( -1 ); - // then apply theme columns to re-compute proportional widths (so we hopefully stay in the view) - applyThemeColumns(); + // then apply theme columns to re-compute proportional widths (so we hopefully stay in the view) + applyThemeColumns(); } Item* View::currentItem() const { - QModelIndex idx = currentIndex(); - if ( !idx.isValid() ) - return 0; - Item * it = static_cast< Item * >( idx.internalPointer() ); - Q_ASSERT( it ); - return it; + QModelIndex idx = currentIndex(); + if ( !idx.isValid() ) + return 0; + Item * it = static_cast< Item * >( idx.internalPointer() ); + Q_ASSERT( it ); + return it; } MessageItem * View::currentMessageItem( bool selectIfNeeded ) const { - Item *it = currentItem(); - if ( !it || ( it->type() != Item::Message ) ) - return 0; - - if ( selectIfNeeded ) - { - // Keep things coherent, if the user didn't select it, but acted on it via - // a shortcut, do select it now. - if ( !selectionModel()->isSelected( currentIndex() ) ) - selectionModel()->select( currentIndex(), QItemSelectionModel::Select | QItemSelectionModel::Current | QItemSelectionModel::Rows ); - } + Item *it = currentItem(); + if ( !it || ( it->type() != Item::Message ) ) + return 0; - return static_cast< MessageItem * >( it ); + if ( selectIfNeeded ) + { + // Keep things coherent, if the user didn't select it, but acted on it via + // a shortcut, do select it now. + if ( !selectionModel()->isSelected( currentIndex() ) ) + selectionModel()->select( currentIndex(), QItemSelectionModel::Select | QItemSelectionModel::Current | QItemSelectionModel::Rows ); + } + + return static_cast< MessageItem * >( it ); } void View::setCurrentMessageItem( MessageItem * it, bool center ) { - if ( it ) - { - kDebug() << "Setting current message to" << it->subject(); - - const QModelIndex index = d->mModel->index( it, 0 ); - selectionModel()->setCurrentIndex( index, QItemSelectionModel::Select | - QItemSelectionModel::Current | QItemSelectionModel::Rows ); - if ( center ) { - scrollTo( index, QAbstractItemView::PositionAtCenter ); - } - } - else - selectionModel()->setCurrentIndex( QModelIndex(), QItemSelectionModel::Current | - QItemSelectionModel::Clear ); + if ( it ) + { + kDebug() << "Setting current message to" << it->subject(); + + const QModelIndex index = d->mModel->index( it, 0 ); + selectionModel()->setCurrentIndex( index, QItemSelectionModel::Select | + QItemSelectionModel::Current | QItemSelectionModel::Rows ); + if ( center ) { + scrollTo( index, QAbstractItemView::PositionAtCenter ); + } + } + else + selectionModel()->setCurrentIndex( QModelIndex(), QItemSelectionModel::Current | + QItemSelectionModel::Clear ); } bool View::selectionEmpty() const { - return selectionModel()->selectedRows().isEmpty(); + return selectionModel()->selectedRows().isEmpty(); } QList< MessageItem * > View::selectionAsMessageItemList( bool includeCollapsedChildren ) const { - QList< MessageItem * > selectedMessages; + QList< MessageItem * > selectedMessages; - QModelIndexList lSelected = selectionModel()->selectedRows(); - if ( lSelected.isEmpty() ) - return selectedMessages; - QModelIndexList::ConstIterator end( lSelected.constEnd() ); - for ( QModelIndexList::ConstIterator it = lSelected.constBegin(); it != end; ++it ) - { - // The asserts below are theoretically valid but at the time - // of writing they fail because of a bug in QItemSelectionModel::selectedRows() - // which returns also non-selectable items. + QModelIndexList lSelected = selectionModel()->selectedRows(); + if ( lSelected.isEmpty() ) + return selectedMessages; + QModelIndexList::ConstIterator end( lSelected.constEnd() ); + for ( QModelIndexList::ConstIterator it = lSelected.constBegin(); it != end; ++it ) + { + // The asserts below are theoretically valid but at the time + // of writing they fail because of a bug in QItemSelectionModel::selectedRows() + // which returns also non-selectable items. - //Q_ASSERT( selectedItem->type() == Item::Message ); - //Q_ASSERT( ( *it ).isValid() ); + //Q_ASSERT( selectedItem->type() == Item::Message ); + //Q_ASSERT( ( *it ).isValid() ); - if ( !( *it ).isValid() ) - continue; + if ( !( *it ).isValid() ) + continue; - Item * selectedItem = static_cast< Item * >( ( *it ).internalPointer() ); - Q_ASSERT( selectedItem ); + Item * selectedItem = static_cast< Item * >( ( *it ).internalPointer() ); + Q_ASSERT( selectedItem ); - if ( selectedItem->type() != Item::Message ) - continue; + if ( selectedItem->type() != Item::Message ) + continue; - if ( !static_cast< MessageItem * >( selectedItem )->isValid() ) - continue; + if ( !static_cast< MessageItem * >( selectedItem )->isValid() ) + continue; - Q_ASSERT( !selectedMessages.contains( static_cast< MessageItem * >( selectedItem ) ) ); + Q_ASSERT( !selectedMessages.contains( static_cast< MessageItem * >( selectedItem ) ) ); - if ( includeCollapsedChildren && ( selectedItem->childItemCount() > 0 ) && ( !isExpanded( *it ) ) ) - { - static_cast< MessageItem * >( selectedItem )->subTreeToList( selectedMessages ); - } else { - selectedMessages.append( static_cast< MessageItem * >( selectedItem ) ); + if ( includeCollapsedChildren && ( selectedItem->childItemCount() > 0 ) && ( !isExpanded( *it ) ) ) + { + static_cast< MessageItem * >( selectedItem )->subTreeToList( selectedMessages ); + } else { + selectedMessages.append( static_cast< MessageItem * >( selectedItem ) ); + } } - } - return selectedMessages; + return selectedMessages; } QList< MessageItem * > View::currentThreadAsMessageItemList() const { - QList< MessageItem * > currentThread; + QList< MessageItem * > currentThread; - MessageItem * msg = currentMessageItem(); - if ( !msg ) - return currentThread; + MessageItem * msg = currentMessageItem(); + if ( !msg ) + return currentThread; - while ( msg->parent() ) - { - if ( msg->parent()->type() != Item::Message ) - break; - msg = static_cast< MessageItem * >( msg->parent() ); - } + while ( msg->parent() ) + { + if ( msg->parent()->type() != Item::Message ) + break; + msg = static_cast< MessageItem * >( msg->parent() ); + } - msg->subTreeToList( currentThread ); + msg->subTreeToList( currentThread ); - return currentThread; + return currentThread; } void View::setChildrenExpanded( const Item * root, bool expand ) { - Q_ASSERT( root ); - QList< Item * > * childList = root->childItems(); - if ( !childList ) - return; - QList< Item * >::ConstIterator end( childList->constEnd() ); - for ( QList< Item * >::ConstIterator it = childList->constBegin(); it != end; ++it ) - { - QModelIndex idx = d->mModel->index( *it, 0 ); - Q_ASSERT( idx.isValid() ); - Q_ASSERT( static_cast< Item * >( idx.internalPointer() ) == ( *it ) ); + Q_ASSERT( root ); + QList< Item * > * childList = root->childItems(); + if ( !childList ) + return; + QList< Item * >::ConstIterator end( childList->constEnd() ); + for ( QList< Item * >::ConstIterator it = childList->constBegin(); it != end; ++it ) + { + QModelIndex idx = d->mModel->index( *it, 0 ); + Q_ASSERT( idx.isValid() ); + Q_ASSERT( static_cast< Item * >( idx.internalPointer() ) == ( *it ) ); - if ( expand ) - { - setExpanded( idx, true ); + if ( expand ) + { + setExpanded( idx, true ); - if ( ( *it )->childItemCount() > 0 ) - setChildrenExpanded( *it, true ); - } else { - if ( ( *it )->childItemCount() > 0 ) - setChildrenExpanded( *it, false ); + if ( ( *it )->childItemCount() > 0 ) + setChildrenExpanded( *it, true ); + } else { + if ( ( *it )->childItemCount() > 0 ) + setChildrenExpanded( *it, false ); - setExpanded( idx, false ); + setExpanded( idx, false ); + } } - } } void View::Private::expandFullThread( const QModelIndex & index ) { - if ( ! index.isValid() ) - return; + if ( ! index.isValid() ) + return; - Item * item = static_cast< Item * >( index.internalPointer() ); - if ( item->type() != Item::Message ) - return; - - if ( ! static_cast< MessageItem * >( item )->parent() || - ( static_cast< MessageItem * >( item )->parent()->type() != Item::Message ) ) - q->setChildrenExpanded( item, true ); + Item * item = static_cast< Item * >( index.internalPointer() ); + if ( item->type() != Item::Message ) + return; + + if ( ! static_cast< MessageItem * >( item )->parent() || + ( static_cast< MessageItem * >( item )->parent()->type() != Item::Message ) ) + q->setChildrenExpanded( item, true ); } void View::setCurrentThreadExpanded( bool expand ) { - Item *it = currentItem(); - if (!it) - return; - - if ( it->type() == Item::GroupHeader ) { - setExpanded( currentIndex(), expand ); - } else if ( it->type() == Item::Message ) { - MessageItem * message = static_cast< MessageItem *>( it ); - while ( message->parent() ) - { - if ( message->parent()->type() != Item::Message ) - break; - message = static_cast< MessageItem * >( message->parent() ); - } + Item *it = currentItem(); + if (!it) + return; + + if ( it->type() == Item::GroupHeader ) { + setExpanded( currentIndex(), expand ); + } else if ( it->type() == Item::Message ) { + MessageItem * message = static_cast< MessageItem *>( it ); + while ( message->parent() ) + { + if ( message->parent()->type() != Item::Message ) + break; + message = static_cast< MessageItem * >( message->parent() ); + } - if ( expand ) - { - setExpanded( d->mModel->index( message, 0 ), true ); - setChildrenExpanded( message, true ); - } else { - setChildrenExpanded( message, false ); - setExpanded( d->mModel->index( message, 0 ), false ); + if ( expand ) + { + setExpanded( d->mModel->index( message, 0 ), true ); + setChildrenExpanded( message, true ); + } else { + setChildrenExpanded( message, false ); + setExpanded( d->mModel->index( message, 0 ), false ); + } } - } } void View::setAllThreadsExpanded( bool expand ) { - if ( d->mAggregation->grouping() == Aggregation::NoGrouping ) - { - // we have no groups so threads start under the root item: just expand/unexpand all - setChildrenExpanded( d->mModel->rootItem(), expand ); - return; - } - - // grouping is in effect: must expand/unexpand one level lower - - QList< Item * > * childList = d->mModel->rootItem()->childItems(); - if ( !childList ) - return; + if ( d->mAggregation->grouping() == Aggregation::NoGrouping ) + { + // we have no groups so threads start under the root item: just expand/unexpand all + setChildrenExpanded( d->mModel->rootItem(), expand ); + return; + } + + // grouping is in effect: must expand/unexpand one level lower - foreach ( Item * item, *childList ) - setChildrenExpanded( item, expand ); + QList< Item * > * childList = d->mModel->rootItem()->childItems(); + if ( !childList ) + return; + + foreach ( Item * item, *childList ) + setChildrenExpanded( item, expand ); } void View::setAllGroupsExpanded( bool expand ) { - if ( d->mAggregation->grouping() == Aggregation::NoGrouping ) - return; // no grouping in effect + if ( d->mAggregation->grouping() == Aggregation::NoGrouping ) + return; // no grouping in effect - Item * item = d->mModel->rootItem(); + Item * item = d->mModel->rootItem(); - QList< Item * > * childList = item->childItems(); - if ( !childList ) - return; - - foreach ( Item * item, *childList ) - { - Q_ASSERT( item->type() == Item::GroupHeader ); - QModelIndex idx = d->mModel->index( item, 0 ); - Q_ASSERT( idx.isValid() ); - Q_ASSERT( static_cast< Item * >( idx.internalPointer() ) == item ); - if ( expand ) { - if ( !isExpanded( idx ) ) - setExpanded( idx, true ); - } else { - if ( isExpanded( idx ) ) - setExpanded( idx, false ); + QList< Item * > * childList = item->childItems(); + if ( !childList ) + return; + + foreach ( Item * item, *childList ) + { + Q_ASSERT( item->type() == Item::GroupHeader ); + QModelIndex idx = d->mModel->index( item, 0 ); + Q_ASSERT( idx.isValid() ); + Q_ASSERT( static_cast< Item * >( idx.internalPointer() ) == item ); + if ( expand ) { + if ( !isExpanded( idx ) ) + setExpanded( idx, true ); + } else { + if ( isExpanded( idx ) ) + setExpanded( idx, false ); + } } - } } void View::selectMessageItems( const QList< MessageItem * > &list ) { - QItemSelection selection; - QList< MessageItem * >::ConstIterator end( list.constEnd() ); - for ( QList< MessageItem * >::ConstIterator it = list.constBegin(); it != end; ++it ) - { - Q_ASSERT( *it ); - QModelIndex idx = d->mModel->index( *it, 0 ); - Q_ASSERT( idx.isValid() ); - Q_ASSERT( static_cast< MessageItem * >( idx.internalPointer() ) == ( *it ) ); - if ( !selectionModel()->isSelected( idx ) ) - selection.append( QItemSelectionRange( idx ) ); - ensureDisplayedWithParentsExpanded( *it ); - } - if ( !selection.isEmpty() ) - selectionModel()->select( selection, QItemSelectionModel::Select | QItemSelectionModel::Rows ); + QItemSelection selection; + QList< MessageItem * >::ConstIterator end( list.constEnd() ); + for ( QList< MessageItem * >::ConstIterator it = list.constBegin(); it != end; ++it ) + { + Q_ASSERT( *it ); + QModelIndex idx = d->mModel->index( *it, 0 ); + Q_ASSERT( idx.isValid() ); + Q_ASSERT( static_cast< MessageItem * >( idx.internalPointer() ) == ( *it ) ); + if ( !selectionModel()->isSelected( idx ) ) + selection.append( QItemSelectionRange( idx ) ); + ensureDisplayedWithParentsExpanded( *it ); + } + if ( !selection.isEmpty() ) + selectionModel()->select( selection, QItemSelectionModel::Select | QItemSelectionModel::Rows ); } static inline bool message_type_matches( Item * item, MessageTypeFilter messageTypeFilter ) { - switch( messageTypeFilter ) - { + switch( messageTypeFilter ) + { case MessageTypeAny: - return true; - break; + return true; + break; case MessageTypeUnreadOnly: - return !item->status().isRead(); - break; + return !item->status().isRead(); + break; default: - // nothing here - break; - } - - // never reached - Q_ASSERT( false ); - return false; + // nothing here + break; + } + + // never reached + Q_ASSERT( false ); + return false; } Item * View::messageItemAfter( Item * referenceItem, MessageTypeFilter messageTypeFilter, bool loop ) { - if ( !storageModel() ) - return 0; // no folder + if ( !storageModel() ) + return 0; // no folder - // find the item to start with - Item * below; + // find the item to start with + Item * below; - if ( referenceItem ) - { - // there was a current item: we start just below it - if ( - ( referenceItem->childItemCount() > 0 ) - && - ( - ( messageTypeFilter != MessageTypeAny ) - || - isExpanded( d->mModel->index( referenceItem, 0 ) ) - ) - ) + if ( referenceItem ) { - // the current item had children: either expanded or we want unread/new messages (and so we'll expand it if it isn't) - below = referenceItem->itemBelow(); - } else { - // the current item had no children: ask the parent to find the item below - Q_ASSERT( referenceItem->parent() ); - below = referenceItem->parent()->itemBelowChild( referenceItem ); - } + // there was a current item: we start just below it + if ( + ( referenceItem->childItemCount() > 0 ) + && + ( + ( messageTypeFilter != MessageTypeAny ) + || + isExpanded( d->mModel->index( referenceItem, 0 ) ) + ) + ) + { + // the current item had children: either expanded or we want unread/new messages (and so we'll expand it if it isn't) + below = referenceItem->itemBelow(); + } else { + // the current item had no children: ask the parent to find the item below + Q_ASSERT( referenceItem->parent() ); + below = referenceItem->parent()->itemBelowChild( referenceItem ); + } - if ( !below ) - { - // reached the end - if ( loop ) - { - // try re-starting from top - below = d->mModel->rootItem()->itemBelow(); - Q_ASSERT( below ); // must exist (we had a current item) + if ( !below ) + { + // reached the end + if ( loop ) + { + // try re-starting from top + below = d->mModel->rootItem()->itemBelow(); + Q_ASSERT( below ); // must exist (we had a current item) - if ( below == referenceItem ) - return 0; // only one item in folder: loop complete - } else { - // looping not requested - return 0; - } - } + if ( below == referenceItem ) + return 0; // only one item in folder: loop complete + } else { + // looping not requested + return 0; + } + } - } else { - // there was no current item, start from beginning - below = d->mModel->rootItem()->itemBelow(); - - if ( !below ) - return 0; // folder empty - } - - // ok.. now below points to the next message. - // While it doesn't satisfy our requirements, go further down - - QModelIndex parentIndex = d->mModel->index( below->parent(), 0 ); - QModelIndex belowIndex = d->mModel->index( below, 0 ); - - Q_ASSERT( belowIndex.isValid() ); - - while ( - // is not a message (we want messages, don't we ?) - ( below->type() != Item::Message ) || - // message filter doesn't match - ( !message_type_matches( below, messageTypeFilter ) ) || - // is hidden (and we don't want hidden items as they arent "officially" in the view) - isRowHidden( belowIndex.row(), parentIndex ) || - // is not enabled or not selectable - ( ( d->mModel->flags( belowIndex ) & ( Qt::ItemIsSelectable | Qt::ItemIsEnabled ) ) != ( Qt::ItemIsSelectable | Qt::ItemIsEnabled ) ) - ) - { - // find the next one - if ( ( below->childItemCount() > 0 ) && ( ( messageTypeFilter != MessageTypeAny ) || isExpanded( belowIndex ) ) ) - { - // the current item had children: either expanded or we want unread messages (and so we'll expand it if it isn't) - below = below->itemBelow(); } else { - // the current item had no children: ask the parent to find the item below - Q_ASSERT( below->parent() ); - below = below->parent()->itemBelowChild( below ); - } - - if ( !below ) - { - // we reached the end of the folder - if ( loop ) - { - // looping requested - if ( referenceItem ) // <-- this means "we have started from something that is not the top: looping makes sense" - below = d->mModel->rootItem()->itemBelow(); - // else mi == 0 and below == 0: we have started from the beginning and reached the end (it will fail the test below and exit) - } else { - // looping not requested: nothing more to do - return 0; - } - } + // there was no current item, start from beginning + below = d->mModel->rootItem()->itemBelow(); - if( below == referenceItem ) - { - Q_ASSERT( loop ); - return 0; // looped and returned back to the first message + if ( !below ) + return 0; // folder empty } - parentIndex = d->mModel->index( below->parent(), 0 ); - belowIndex = d->mModel->index( below, 0 ); + // ok.. now below points to the next message. + // While it doesn't satisfy our requirements, go further down + + QModelIndex parentIndex = d->mModel->index( below->parent(), 0 ); + QModelIndex belowIndex = d->mModel->index( below, 0 ); Q_ASSERT( belowIndex.isValid() ); - } - return below; + while ( + // is not a message (we want messages, don't we ?) + ( below->type() != Item::Message ) || + // message filter doesn't match + ( !message_type_matches( below, messageTypeFilter ) ) || + // is hidden (and we don't want hidden items as they arent "officially" in the view) + isRowHidden( belowIndex.row(), parentIndex ) || + // is not enabled or not selectable + ( ( d->mModel->flags( belowIndex ) & ( Qt::ItemIsSelectable | Qt::ItemIsEnabled ) ) != ( Qt::ItemIsSelectable | Qt::ItemIsEnabled ) ) + ) + { + // find the next one + if ( ( below->childItemCount() > 0 ) && ( ( messageTypeFilter != MessageTypeAny ) || isExpanded( belowIndex ) ) ) + { + // the current item had children: either expanded or we want unread messages (and so we'll expand it if it isn't) + below = below->itemBelow(); + } else { + // the current item had no children: ask the parent to find the item below + Q_ASSERT( below->parent() ); + below = below->parent()->itemBelowChild( below ); + } + + if ( !below ) + { + // we reached the end of the folder + if ( loop ) + { + // looping requested + if ( referenceItem ) // <-- this means "we have started from something that is not the top: looping makes sense" + below = d->mModel->rootItem()->itemBelow(); + // else mi == 0 and below == 0: we have started from the beginning and reached the end (it will fail the test below and exit) + } else { + // looping not requested: nothing more to do + return 0; + } + } + + if( below == referenceItem ) + { + Q_ASSERT( loop ); + return 0; // looped and returned back to the first message + } + + parentIndex = d->mModel->index( below->parent(), 0 ); + belowIndex = d->mModel->index( below, 0 ); + + Q_ASSERT( belowIndex.isValid() ); + } + + return below; } Item * View::nextMessageItem( MessageTypeFilter messageTypeFilter, bool loop ) { - return messageItemAfter( currentMessageItem( false ), messageTypeFilter, loop ); + return messageItemAfter( currentMessageItem( false ), messageTypeFilter, loop ); } Item * View::deepestExpandedChild( Item * referenceItem ) const { - const int children = referenceItem->childItemCount(); - if ( children > 0 && - isExpanded( d->mModel->index( referenceItem, 0 ) ) ) { - return deepestExpandedChild( referenceItem->childItem( children -1 ) ); - } - else - return referenceItem; + const int children = referenceItem->childItemCount(); + if ( children > 0 && + isExpanded( d->mModel->index( referenceItem, 0 ) ) ) { + return deepestExpandedChild( referenceItem->childItem( children -1 ) ); + } + else + return referenceItem; } Item * View::messageItemBefore( Item * referenceItem, MessageTypeFilter messageTypeFilter, bool loop ) { - if ( !storageModel() ) - return 0; // no folder + if ( !storageModel() ) + return 0; // no folder - // find the item to start with - Item * above; + // find the item to start with + Item * above; - if ( referenceItem ) - { - Item *parent = referenceItem->parent(); - Item *siblingAbove = parent ? - parent->itemAboveChild( referenceItem ) : 0; - // there was a current item: we start just above it - if ( ( siblingAbove && siblingAbove != referenceItem && siblingAbove != parent ) && - ( siblingAbove->childItemCount() > 0 ) && - ( - ( messageTypeFilter != MessageTypeAny ) || - ( isExpanded( d->mModel->index( siblingAbove, 0 ) ) ) - ) - ) + if ( referenceItem ) { - // the current item had children: either expanded or we want unread/new messages (and so we'll expand it if it isn't) - above = deepestExpandedChild( siblingAbove ); + Item *parent = referenceItem->parent(); + Item *siblingAbove = parent ? + parent->itemAboveChild( referenceItem ) : 0; + // there was a current item: we start just above it + if ( ( siblingAbove && siblingAbove != referenceItem && siblingAbove != parent ) && + ( siblingAbove->childItemCount() > 0 ) && + ( + ( messageTypeFilter != MessageTypeAny ) || + ( isExpanded( d->mModel->index( siblingAbove, 0 ) ) ) + ) + ) + { + // the current item had children: either expanded or we want unread/new messages (and so we'll expand it if it isn't) + above = deepestExpandedChild( siblingAbove ); + } else { + // the current item had no children: ask the parent to find the item above + Q_ASSERT( referenceItem->parent() ); + above = referenceItem->parent()->itemAboveChild( referenceItem ); + } + + if ( ( !above ) || ( above == d->mModel->rootItem() ) ) + { + // reached the beginning + if ( loop ) + { + // try re-starting from bottom + above = d->mModel->rootItem()->deepestItem(); + Q_ASSERT( above ); // must exist (we had a current item) + Q_ASSERT( above != d->mModel->rootItem() ); + + if ( above == referenceItem ) + return 0; // only one item in folder: loop complete + } else { + // looping not requested + return 0; + } + + } } else { - // the current item had no children: ask the parent to find the item above - Q_ASSERT( referenceItem->parent() ); - above = referenceItem->parent()->itemAboveChild( referenceItem ); + // there was no current item, start from end + above = d->mModel->rootItem()->deepestItem(); + + if ( !above || !above->parent() || ( above == d->mModel->rootItem() ) ) + return 0; // folder empty } - if ( ( !above ) || ( above == d->mModel->rootItem() ) ) - { - // reached the beginning - if ( loop ) - { - // try re-starting from bottom - above = d->mModel->rootItem()->deepestItem(); - Q_ASSERT( above ); // must exist (we had a current item) - Q_ASSERT( above != d->mModel->rootItem() ); + // ok.. now below points to the previous message. + // While it doesn't satisfy our requirements, go further up - if ( above == referenceItem ) - return 0; // only one item in folder: loop complete - } else { - // looping not requested - return 0; - } + QModelIndex parentIndex = d->mModel->index( above->parent(), 0 ); + QModelIndex aboveIndex = d->mModel->index( above, 0 ); - } - } else { - // there was no current item, start from end - above = d->mModel->rootItem()->deepestItem(); - - if ( !above || !above->parent() || ( above == d->mModel->rootItem() ) ) - return 0; // folder empty - } - - // ok.. now below points to the previous message. - // While it doesn't satisfy our requirements, go further up - - QModelIndex parentIndex = d->mModel->index( above->parent(), 0 ); - QModelIndex aboveIndex = d->mModel->index( above, 0 ); - - Q_ASSERT( aboveIndex.isValid() ); - - while ( - // is not a message (we want messages, don't we ?) - ( above->type() != Item::Message ) || - // message filter doesn't match - ( !message_type_matches( above, messageTypeFilter ) ) || - // we don't expand items but the item has parents unexpanded (so should be skipped) - ( - // !expand items - ( messageTypeFilter == MessageTypeAny ) && - // has unexpanded parents or is itself hidden - ( ! isDisplayedWithParentsExpanded( above ) ) - ) || - // is hidden - isRowHidden( aboveIndex.row(), parentIndex ) || - // is not enabled or not selectable - ( ( d->mModel->flags( aboveIndex ) & ( Qt::ItemIsSelectable | Qt::ItemIsEnabled ) ) != ( Qt::ItemIsSelectable | Qt::ItemIsEnabled ) ) - ) - { - - above = above->itemAbove(); - - if ( ( !above ) || ( above == d->mModel->rootItem() ) ) - { - // reached the beginning - if ( loop ) - { - // looping requested - if ( referenceItem ) // <-- this means "we have started from something that is not the beginning: looping makes sense" - above = d->mModel->rootItem()->deepestItem(); - // else mi == 0 and above == 0: we have started from the end and reached the beginning (it will fail the test below and exit) - } else { - // looping not requested: nothing more to do - return 0; - } - } + Q_ASSERT( aboveIndex.isValid() ); - if( above == referenceItem ) + while ( + // is not a message (we want messages, don't we ?) + ( above->type() != Item::Message ) || + // message filter doesn't match + ( !message_type_matches( above, messageTypeFilter ) ) || + // we don't expand items but the item has parents unexpanded (so should be skipped) + ( + // !expand items + ( messageTypeFilter == MessageTypeAny ) && + // has unexpanded parents or is itself hidden + ( ! isDisplayedWithParentsExpanded( above ) ) + ) || + // is hidden + isRowHidden( aboveIndex.row(), parentIndex ) || + // is not enabled or not selectable + ( ( d->mModel->flags( aboveIndex ) & ( Qt::ItemIsSelectable | Qt::ItemIsEnabled ) ) != ( Qt::ItemIsSelectable | Qt::ItemIsEnabled ) ) + ) { - Q_ASSERT( loop ); - return 0; // looped and returned back to the first message - } - if(!above->parent()) - return 0; + above = above->itemAbove(); - parentIndex = d->mModel->index( above->parent(), 0 ); - aboveIndex = d->mModel->index( above, 0 ); + if ( ( !above ) || ( above == d->mModel->rootItem() ) ) + { + // reached the beginning + if ( loop ) + { + // looping requested + if ( referenceItem ) // <-- this means "we have started from something that is not the beginning: looping makes sense" + above = d->mModel->rootItem()->deepestItem(); + // else mi == 0 and above == 0: we have started from the end and reached the beginning (it will fail the test below and exit) + } else { + // looping not requested: nothing more to do + return 0; + } + } - Q_ASSERT( aboveIndex.isValid() ); - } + if( above == referenceItem ) + { + Q_ASSERT( loop ); + return 0; // looped and returned back to the first message + } + + if(!above->parent()) + return 0; - return above; + parentIndex = d->mModel->index( above->parent(), 0 ); + aboveIndex = d->mModel->index( above, 0 ); + + Q_ASSERT( aboveIndex.isValid() ); + } + + return above; } Item * View::previousMessageItem( MessageTypeFilter messageTypeFilter, bool loop ) { - return messageItemBefore( currentMessageItem( false ), messageTypeFilter, loop ); + return messageItemBefore( currentMessageItem( false ), messageTypeFilter, loop ); } void View::growOrShrinkExistingSelection( const QModelIndex &newSelectedIndex, bool movingUp ) { - // Qt: why visualIndex() is private? ...I'd really need it here... + // Qt: why visualIndex() is private? ...I'd really need it here... - int selectedVisualCoordinate = visualRect( newSelectedIndex ).top(); + int selectedVisualCoordinate = visualRect( newSelectedIndex ).top(); - int topVisualCoordinate = 0xfffffff; // huuuuuge number - int bottomVisualCoordinate = -(0xfffffff); + int topVisualCoordinate = 0xfffffff; // huuuuuge number + int bottomVisualCoordinate = -(0xfffffff); - int candidate; + int candidate; - QModelIndex bottomIndex; - QModelIndex topIndex; + QModelIndex bottomIndex; + QModelIndex topIndex; - // find out the actual selection range - const QItemSelection selection = selectionModel()->selection(); + // find out the actual selection range + const QItemSelection selection = selectionModel()->selection(); - foreach ( const QItemSelectionRange &range, selection ) - { - // We're asking the model for the index as range.topLeft() and range.bottomRight() - // can return indexes in invisible columns which have a null visualRect(). - // Column 0, instead, is always visible. + foreach ( const QItemSelectionRange &range, selection ) + { + // We're asking the model for the index as range.topLeft() and range.bottomRight() + // can return indexes in invisible columns which have a null visualRect(). + // Column 0, instead, is always visible. - QModelIndex top = d->mModel->index( range.top(), 0, range.parent() ); - QModelIndex bottom = d->mModel->index( range.bottom(), 0, range.parent() ); + QModelIndex top = d->mModel->index( range.top(), 0, range.parent() ); + QModelIndex bottom = d->mModel->index( range.bottom(), 0, range.parent() ); - if ( top.isValid() ) - { - if ( !bottom.isValid() ) - bottom = top; - } else { - if ( !top.isValid() ) - top = bottom; - } - candidate = visualRect( bottom ).bottom(); - if ( candidate > bottomVisualCoordinate ) - { - bottomVisualCoordinate = candidate; - bottomIndex = range.bottomRight(); - } + if ( top.isValid() ) + { + if ( !bottom.isValid() ) + bottom = top; + } else { + if ( !top.isValid() ) + top = bottom; + } + candidate = visualRect( bottom ).bottom(); + if ( candidate > bottomVisualCoordinate ) + { + bottomVisualCoordinate = candidate; + bottomIndex = range.bottomRight(); + } - candidate = visualRect( top ).top(); - if ( candidate < topVisualCoordinate ) - { - topVisualCoordinate = candidate; - topIndex = range.topLeft(); + candidate = visualRect( top ).top(); + if ( candidate < topVisualCoordinate ) + { + topVisualCoordinate = candidate; + topIndex = range.topLeft(); + } } - } - if ( topIndex.isValid() && bottomIndex.isValid() ) - { - if ( movingUp ) + if ( topIndex.isValid() && bottomIndex.isValid() ) { - if ( selectedVisualCoordinate < topVisualCoordinate ) - { - // selecting something above the top: grow selection - selectionModel()->select( newSelectedIndex, QItemSelectionModel::Rows | QItemSelectionModel::Select ); - } else { - // selecting something below the top: shrink selection - QModelIndexList selectedIndexes = selection.indexes(); - foreach ( const QModelIndex &idx, selectedIndexes ) + if ( movingUp ) { - if ( ( idx.column() == 0 ) && ( visualRect( idx ).top() > selectedVisualCoordinate ) ) - selectionModel()->select( idx, QItemSelectionModel::Rows | QItemSelectionModel::Deselect ); + if ( selectedVisualCoordinate < topVisualCoordinate ) + { + // selecting something above the top: grow selection + selectionModel()->select( newSelectedIndex, QItemSelectionModel::Rows | QItemSelectionModel::Select ); + } else { + // selecting something below the top: shrink selection + QModelIndexList selectedIndexes = selection.indexes(); + foreach ( const QModelIndex &idx, selectedIndexes ) + { + if ( ( idx.column() == 0 ) && ( visualRect( idx ).top() > selectedVisualCoordinate ) ) + selectionModel()->select( idx, QItemSelectionModel::Rows | QItemSelectionModel::Deselect ); + } + } + } else { + if ( selectedVisualCoordinate > bottomVisualCoordinate ) + { + // selecting something below bottom: grow selection + selectionModel()->select( newSelectedIndex, QItemSelectionModel::Rows | QItemSelectionModel::Select ); + } else { + // selecting something above bottom: shrink selection + QModelIndexList selectedIndexes = selection.indexes(); + foreach ( const QModelIndex &idx, selectedIndexes ) + { + if ( ( idx.column() == 0 ) && ( visualRect( idx ).top() < selectedVisualCoordinate ) ) + selectionModel()->select( idx, QItemSelectionModel::Rows | QItemSelectionModel::Deselect ); + } + } } - } } else { - if ( selectedVisualCoordinate > bottomVisualCoordinate ) - { - // selecting something below bottom: grow selection + // no existing selection, just grow selectionModel()->select( newSelectedIndex, QItemSelectionModel::Rows | QItemSelectionModel::Select ); - } else { - // selecting something above bottom: shrink selection - QModelIndexList selectedIndexes = selection.indexes(); - foreach ( const QModelIndex &idx, selectedIndexes ) - { - if ( ( idx.column() == 0 ) && ( visualRect( idx ).top() < selectedVisualCoordinate ) ) - selectionModel()->select( idx, QItemSelectionModel::Rows | QItemSelectionModel::Deselect ); - } - } - } - } else { - // no existing selection, just grow - selectionModel()->select( newSelectedIndex, QItemSelectionModel::Rows | QItemSelectionModel::Select ); - } + } } bool View::selectNextMessageItem( - MessageTypeFilter messageTypeFilter, - ExistingSelectionBehaviour existingSelectionBehaviour, - bool centerItem, - bool loop - ) -{ - Item * it = nextMessageItem( messageTypeFilter, loop ); - if ( !it ) - return false; + MessageTypeFilter messageTypeFilter, + ExistingSelectionBehaviour existingSelectionBehaviour, + bool centerItem, + bool loop + ) +{ + Item * it = nextMessageItem( messageTypeFilter, loop ); + if ( !it ) + return false; - setFocus(); + setFocus(); - if ( it->parent() != d->mModel->rootItem() ) - ensureDisplayedWithParentsExpanded( it ); + if ( it->parent() != d->mModel->rootItem() ) + ensureDisplayedWithParentsExpanded( it ); - QModelIndex idx = d->mModel->index( it, 0 ); + QModelIndex idx = d->mModel->index( it, 0 ); - Q_ASSERT( idx.isValid() ); + Q_ASSERT( idx.isValid() ); - switch ( existingSelectionBehaviour ) - { + switch ( existingSelectionBehaviour ) + { case ExpandExistingSelection: - selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); - selectionModel()->select( idx, QItemSelectionModel::Rows | QItemSelectionModel::Select ); - break; + selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); + selectionModel()->select( idx, QItemSelectionModel::Rows | QItemSelectionModel::Select ); + break; case GrowOrShrinkExistingSelection: - selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); - growOrShrinkExistingSelection( idx, false ); - break; + selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); + growOrShrinkExistingSelection( idx, false ); + break; default: - //case ClearExistingSelection: - setCurrentIndex( idx ); - break; - } + //case ClearExistingSelection: + setCurrentIndex( idx ); + break; + } - if ( centerItem ) - scrollTo( idx, QAbstractItemView::PositionAtCenter ); + if ( centerItem ) + scrollTo( idx, QAbstractItemView::PositionAtCenter ); - return true; + return true; } bool View::selectPreviousMessageItem( - MessageTypeFilter messageTypeFilter, - ExistingSelectionBehaviour existingSelectionBehaviour, - bool centerItem, - bool loop - ) -{ - Item * it = previousMessageItem( messageTypeFilter, loop ); - if ( !it ) - return false; + MessageTypeFilter messageTypeFilter, + ExistingSelectionBehaviour existingSelectionBehaviour, + bool centerItem, + bool loop + ) +{ + Item * it = previousMessageItem( messageTypeFilter, loop ); + if ( !it ) + return false; - setFocus(); + setFocus(); - if ( it->parent() != d->mModel->rootItem() ) - ensureDisplayedWithParentsExpanded( it ); + if ( it->parent() != d->mModel->rootItem() ) + ensureDisplayedWithParentsExpanded( it ); - QModelIndex idx = d->mModel->index( it, 0 ); + QModelIndex idx = d->mModel->index( it, 0 ); - Q_ASSERT( idx.isValid() ); + Q_ASSERT( idx.isValid() ); - switch ( existingSelectionBehaviour ) - { + switch ( existingSelectionBehaviour ) + { case ExpandExistingSelection: - selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); - selectionModel()->select( idx, QItemSelectionModel::Rows | QItemSelectionModel::Select ); - break; + selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); + selectionModel()->select( idx, QItemSelectionModel::Rows | QItemSelectionModel::Select ); + break; case GrowOrShrinkExistingSelection: - selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); - growOrShrinkExistingSelection( idx, true ); - break; + selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); + growOrShrinkExistingSelection( idx, true ); + break; default: - //case ClearExistingSelection: - setCurrentIndex( idx ); - break; - } + //case ClearExistingSelection: + setCurrentIndex( idx ); + break; + } - if ( centerItem ) - scrollTo( idx, QAbstractItemView::PositionAtCenter ); + if ( centerItem ) + scrollTo( idx, QAbstractItemView::PositionAtCenter ); - return true; + return true; } bool View::focusNextMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ) { - Item * it = nextMessageItem( messageTypeFilter, loop ); - if ( !it ) - return false; + Item * it = nextMessageItem( messageTypeFilter, loop ); + if ( !it ) + return false; - setFocus(); + setFocus(); - if ( it->parent() != d->mModel->rootItem() ) - ensureDisplayedWithParentsExpanded( it ); + if ( it->parent() != d->mModel->rootItem() ) + ensureDisplayedWithParentsExpanded( it ); - QModelIndex idx = d->mModel->index( it, 0 ); + QModelIndex idx = d->mModel->index( it, 0 ); - Q_ASSERT( idx.isValid() ); + Q_ASSERT( idx.isValid() ); - selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); + selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); - if ( centerItem ) - scrollTo( idx, QAbstractItemView::PositionAtCenter ); + if ( centerItem ) + scrollTo( idx, QAbstractItemView::PositionAtCenter ); - return true; + return true; } bool View::focusPreviousMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ) { - Item * it = previousMessageItem( messageTypeFilter, loop ); - if ( !it ) - return false; + Item * it = previousMessageItem( messageTypeFilter, loop ); + if ( !it ) + return false; - setFocus(); + setFocus(); - if ( it->parent() != d->mModel->rootItem() ) - ensureDisplayedWithParentsExpanded( it ); + if ( it->parent() != d->mModel->rootItem() ) + ensureDisplayedWithParentsExpanded( it ); - QModelIndex idx = d->mModel->index( it, 0 ); + QModelIndex idx = d->mModel->index( it, 0 ); - Q_ASSERT( idx.isValid() ); + Q_ASSERT( idx.isValid() ); - selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); + selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); - if ( centerItem ) - scrollTo( idx, QAbstractItemView::PositionAtCenter ); + if ( centerItem ) + scrollTo( idx, QAbstractItemView::PositionAtCenter ); - return true; + return true; } void View::selectFocusedMessageItem( bool centerItem ) { - QModelIndex idx = currentIndex(); - if ( !idx.isValid() ) - return; + QModelIndex idx = currentIndex(); + if ( !idx.isValid() ) + return; - setFocus(); + setFocus(); - if ( selectionModel()->isSelected( idx ) ) - return; + if ( selectionModel()->isSelected( idx ) ) + return; - selectionModel()->select( idx, QItemSelectionModel::Select | QItemSelectionModel::Current | QItemSelectionModel::Rows ); + selectionModel()->select( idx, QItemSelectionModel::Select | QItemSelectionModel::Current | QItemSelectionModel::Rows ); - if ( centerItem ) - scrollTo( idx, QAbstractItemView::PositionAtCenter ); + if ( centerItem ) + scrollTo( idx, QAbstractItemView::PositionAtCenter ); } bool View::selectFirstMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem ) { - if ( !storageModel() ) - return false; // nothing to do + if ( !storageModel() ) + return false; // nothing to do - Item * it = firstMessageItem( messageTypeFilter ); - if ( !it ) - return false; + Item * it = firstMessageItem( messageTypeFilter ); + if ( !it ) + return false; - Q_ASSERT( it != d->mModel->rootItem() ); // must never happen (obviously) + Q_ASSERT( it != d->mModel->rootItem() ); // must never happen (obviously) - setFocus(); - ensureDisplayedWithParentsExpanded( it ); + setFocus(); + ensureDisplayedWithParentsExpanded( it ); - QModelIndex idx = d->mModel->index( it, 0 ); + QModelIndex idx = d->mModel->index( it, 0 ); - Q_ASSERT( idx.isValid() ); + Q_ASSERT( idx.isValid() ); - setCurrentIndex( idx ); + setCurrentIndex( idx ); - if ( centerItem ) - scrollTo( idx, QAbstractItemView::PositionAtCenter ); + if ( centerItem ) + scrollTo( idx, QAbstractItemView::PositionAtCenter ); - return true; + return true; } bool View::selectLastMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem ) { - if ( !storageModel() ) - return false; + if ( !storageModel() ) + return false; - Item * it = lastMessageItem( messageTypeFilter ); - if ( !it ) - return false; + Item * it = lastMessageItem( messageTypeFilter ); + if ( !it ) + return false; - Q_ASSERT( it != d->mModel->rootItem() ); + Q_ASSERT( it != d->mModel->rootItem() ); - setFocus(); - ensureDisplayedWithParentsExpanded( it ); + setFocus(); + ensureDisplayedWithParentsExpanded( it ); - QModelIndex idx = d->mModel->index( it, 0 ); + QModelIndex idx = d->mModel->index( it, 0 ); - Q_ASSERT( idx.isValid() ); + Q_ASSERT( idx.isValid() ); - setCurrentIndex( idx ); + setCurrentIndex( idx ); - if ( centerItem ) - scrollTo( idx, QAbstractItemView::PositionAtCenter ); + if ( centerItem ) + scrollTo( idx, QAbstractItemView::PositionAtCenter ); - return true; + return true; } void View::modelFinishedLoading() { - Q_ASSERT( storageModel() ); - Q_ASSERT( !d->mModel->isLoading() ); + Q_ASSERT( storageModel() ); + Q_ASSERT( !d->mModel->isLoading() ); - // nothing here for now :) + // nothing here for now :) } MessageItemSetReference View::createPersistentSet( const QList< MessageItem * > &items ) { - return d->mModel->createPersistentSet( items ); + return d->mModel->createPersistentSet( items ); } QList< MessageItem * > View::persistentSetCurrentMessageItemList( MessageItemSetReference ref ) { - return d->mModel->persistentSetCurrentMessageItemList( ref ); + return d->mModel->persistentSetCurrentMessageItemList( ref ); } void View::deletePersistentSet( MessageItemSetReference ref ) { - d->mModel->deletePersistentSet( ref ); + d->mModel->deletePersistentSet( ref ); } void View::markMessageItemsAsAboutToBeRemoved( QList< MessageItem * > &items, bool bMark ) { - if ( !bMark ) - { - QList< MessageItem * >::ConstIterator end( items.constEnd() ); - for ( QList< MessageItem * >::ConstIterator it = items.constBegin(); it != end; ++it ) + if ( !bMark ) { - if ( ( *it )->isValid() ) // hasn't been removed in the meantime - ( *it )->setAboutToBeRemoved( false ); - } + QList< MessageItem * >::ConstIterator end( items.constEnd() ); + for ( QList< MessageItem * >::ConstIterator it = items.constBegin(); it != end; ++it ) + { + if ( ( *it )->isValid() ) // hasn't been removed in the meantime + ( *it )->setAboutToBeRemoved( false ); + } - viewport()->update(); + viewport()->update(); - return; - } + return; + } - // ok.. we're going to mark the messages as "about to be deleted". - // This means that we're going to make them non selectable. + // ok.. we're going to mark the messages as "about to be deleted". + // This means that we're going to make them non selectable. - // What happens to the selection is generally an untrackable big mess. - // Several components and entities are involved. + // What happens to the selection is generally an untrackable big mess. + // Several components and entities are involved. - // Qutie tries to apply some kind of internal logic in order to keep - // "something" selected and "something" (else) to be current. - // The results sometimes appear to depend on the current moon phase. + // Qutie tries to apply some kind of internal logic in order to keep + // "something" selected and "something" (else) to be current. + // The results sometimes appear to depend on the current moon phase. - // The Model will do crazy things in order to preserve the current - // selection (and possibly the current item). If it's impossible then - // it will make its own guesses about what should be selected next. - // A problem is that the Model will do it one message at a time. - // When item reparenting/reordering is involved then the guesses - // can produce non-intuitive results. + // The Model will do crazy things in order to preserve the current + // selection (and possibly the current item). If it's impossible then + // it will make its own guesses about what should be selected next. + // A problem is that the Model will do it one message at a time. + // When item reparenting/reordering is involved then the guesses + // can produce non-intuitive results. - // Add the fact that selection and current item are distinct concepts, - // their relative interaction depends on the settings and is often quite - // unclear. + // Add the fact that selection and current item are distinct concepts, + // their relative interaction depends on the settings and is often quite + // unclear. - // Add the fact that (at the time of writing) several styles don't show - // the current item (only Yoda knows why) and this causes some confusion to the user. + // Add the fact that (at the time of writing) several styles don't show + // the current item (only Yoda knows why) and this causes some confusion to the user. - // Add the fact that the operations are asynchronous: deletion will start - // a job, do some event loop processing and then complete the work at a later time. - // The Qutie views also tend to accumulate the changes and perform them - // all at once at the latest possible stage. + // Add the fact that the operations are asynchronous: deletion will start + // a job, do some event loop processing and then complete the work at a later time. + // The Qutie views also tend to accumulate the changes and perform them + // all at once at the latest possible stage. - // A radical approach is needed: we FIRST deal with the selection - // by tring to move it away from the messages about to be deleted - // and THEN mark the (hopefully no longer selected) messages as "about to be deleted". + // A radical approach is needed: we FIRST deal with the selection + // by tring to move it away from the messages about to be deleted + // and THEN mark the (hopefully no longer selected) messages as "about to be deleted". - // First of all, find out if we're going to clear the entire selection (very likely). + // First of all, find out if we're going to clear the entire selection (very likely). - bool clearingEntireSelection = true; + bool clearingEntireSelection = true; - QModelIndexList selectedIndexes = selectionModel()->selectedRows( 0 ); + QModelIndexList selectedIndexes = selectionModel()->selectedRows( 0 ); - if ( selectedIndexes.count() > items.count() ) - { - // the selection is bigger: we can't clear it completely - clearingEntireSelection = false; - } else { - // the selection has same size or is smaller: we can clear it completely with our removal - foreach ( const QModelIndex &selectedIndex , selectedIndexes ) + if ( selectedIndexes.count() > items.count() ) { - Q_ASSERT( selectedIndex.isValid() ); - Q_ASSERT( selectedIndex.column() == 0 ); + // the selection is bigger: we can't clear it completely + clearingEntireSelection = false; + } else { + // the selection has same size or is smaller: we can clear it completely with our removal + foreach ( const QModelIndex &selectedIndex , selectedIndexes ) + { + Q_ASSERT( selectedIndex.isValid() ); + Q_ASSERT( selectedIndex.column() == 0 ); - Item * selectedItem = static_cast< Item * >( selectedIndex.internalPointer() ); - Q_ASSERT( selectedItem ); + Item * selectedItem = static_cast< Item * >( selectedIndex.internalPointer() ); + Q_ASSERT( selectedItem ); - if ( selectedItem->type() != Item::Message ) - continue; + if ( selectedItem->type() != Item::Message ) + continue; - if ( !items.contains( static_cast< MessageItem * >( selectedItem ) ) ) - { - // the selection contains something that we aren't going to remove: - // we will not clear the selection completely - clearingEntireSelection = false; - break; - } + if ( !items.contains( static_cast< MessageItem * >( selectedItem ) ) ) + { + // the selection contains something that we aren't going to remove: + // we will not clear the selection completely + clearingEntireSelection = false; + break; + } + } } - } - if ( clearingEntireSelection ) - { - // Try to clear the current selection and select something sensible instead, - // so after the deletion we will not end up with a random selection. - // Pick up a message in the set (which is very likely to be contiguous), walk the tree - // and select the next message that is NOT in the set. + if ( clearingEntireSelection ) + { + // Try to clear the current selection and select something sensible instead, + // so after the deletion we will not end up with a random selection. + // Pick up a message in the set (which is very likely to be contiguous), walk the tree + // and select the next message that is NOT in the set. - MessageItem * aMessage = items.last(); - Q_ASSERT( aMessage ); + MessageItem * aMessage = items.last(); + Q_ASSERT( aMessage ); - // Avoid infinite loops by carrying only a limited number of attempts. - // If there is any message that is not in the set then items.count() attemps should find it. - int maxAttempts = items.count(); + // Avoid infinite loops by carrying only a limited number of attempts. + // If there is any message that is not in the set then items.count() attemps should find it. + int maxAttempts = items.count(); - while ( items.contains( aMessage ) && ( maxAttempts > 0 ) ) - { - Item * next = messageItemAfter( aMessage, MessageTypeAny, false ); - if ( !next ) - { - // no way - aMessage = 0; - break; - } - Q_ASSERT( next->type() == Item::Message ); - aMessage = static_cast< MessageItem * >( next ); - maxAttempts--; - } + while ( items.contains( aMessage ) && ( maxAttempts > 0 ) ) + { + Item * next = messageItemAfter( aMessage, MessageTypeAny, false ); + if ( !next ) + { + // no way + aMessage = 0; + break; + } + Q_ASSERT( next->type() == Item::Message ); + aMessage = static_cast< MessageItem * >( next ); + maxAttempts--; + } - if ( !aMessage ) - { - // try backwards - aMessage = items.first(); - Q_ASSERT( aMessage ); - maxAttempts = items.count(); + if ( !aMessage ) + { + // try backwards + aMessage = items.first(); + Q_ASSERT( aMessage ); + maxAttempts = items.count(); + + while ( items.contains( aMessage ) && ( maxAttempts > 0 ) ) + { + Item * prev = messageItemBefore( aMessage, MessageTypeAny, false ); + if ( !prev ) + { + // no way + aMessage = 0; + break; + } + Q_ASSERT( prev->type() == Item::Message ); + aMessage = static_cast< MessageItem * >( prev ); + maxAttempts--; + } + } - while ( items.contains( aMessage ) && ( maxAttempts > 0 ) ) - { - Item * prev = messageItemBefore( aMessage, MessageTypeAny, false ); - if ( !prev ) + if ( aMessage ) { - // no way - aMessage = 0; - break; + QModelIndex aMessageIndex = d->mModel->index( aMessage, 0 ); + Q_ASSERT( aMessageIndex.isValid() ); + Q_ASSERT( static_cast< MessageItem * >( aMessageIndex.internalPointer() ) == aMessage ); + Q_ASSERT( !selectionModel()->isSelected( aMessageIndex ) ); + setCurrentIndex( aMessageIndex ); + selectionModel()->select( aMessageIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows ); } - Q_ASSERT( prev->type() == Item::Message ); - aMessage = static_cast< MessageItem * >( prev ); - maxAttempts--; - } - } + } // else we aren't clearing the entire selection so something should just stay selected. - if ( aMessage ) + // Now mark messages as about to be removed. + + QList< MessageItem * >::ConstIterator end( items.constEnd() ); + for ( QList< MessageItem * >::ConstIterator it = items.constBegin(); it != end; ++it ) { - QModelIndex aMessageIndex = d->mModel->index( aMessage, 0 ); - Q_ASSERT( aMessageIndex.isValid() ); - Q_ASSERT( static_cast< MessageItem * >( aMessageIndex.internalPointer() ) == aMessage ); - Q_ASSERT( !selectionModel()->isSelected( aMessageIndex ) ); - setCurrentIndex( aMessageIndex ); - selectionModel()->select( aMessageIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows ); + ( *it )->setAboutToBeRemoved( true ); + QModelIndex idx = d->mModel->index( *it, 0 ); + Q_ASSERT( idx.isValid() ); + Q_ASSERT( static_cast< MessageItem * >( idx.internalPointer() ) == *it ); + if ( selectionModel()->isSelected( idx ) ) + selectionModel()->select( idx, QItemSelectionModel::Deselect | QItemSelectionModel::Rows ); } - } // else we aren't clearing the entire selection so something should just stay selected. - - // Now mark messages as about to be removed. - - QList< MessageItem * >::ConstIterator end( items.constEnd() ); - for ( QList< MessageItem * >::ConstIterator it = items.constBegin(); it != end; ++it ) - { - ( *it )->setAboutToBeRemoved( true ); - QModelIndex idx = d->mModel->index( *it, 0 ); - Q_ASSERT( idx.isValid() ); - Q_ASSERT( static_cast< MessageItem * >( idx.internalPointer() ) == *it ); - if ( selectionModel()->isSelected( idx ) ) - selectionModel()->select( idx, QItemSelectionModel::Deselect | QItemSelectionModel::Rows ); - } - viewport()->update(); + viewport()->update(); } void View::ensureDisplayedWithParentsExpanded( Item * it ) { - Q_ASSERT( it ); - Q_ASSERT( it->parent() ); - Q_ASSERT( it->isViewable() ); // must be attached to the viewable root + Q_ASSERT( it ); + Q_ASSERT( it->parent() ); + Q_ASSERT( it->isViewable() ); // must be attached to the viewable root - if ( isRowHidden( it->parent()->indexOfChildItem( it ), d->mModel->index( it->parent(), 0 ) ) ) - setRowHidden( it->parent()->indexOfChildItem( it ), d->mModel->index( it->parent(), 0 ), false ); + if ( isRowHidden( it->parent()->indexOfChildItem( it ), d->mModel->index( it->parent(), 0 ) ) ) + setRowHidden( it->parent()->indexOfChildItem( it ), d->mModel->index( it->parent(), 0 ), false ); - it = it->parent(); + it = it->parent(); - while ( it->parent() ) - { - if ( isRowHidden( it->parent()->indexOfChildItem( it ), d->mModel->index( it->parent(), 0 ) ) ) - setRowHidden( it->parent()->indexOfChildItem( it ), d->mModel->index( it->parent(), 0 ), false ); + while ( it->parent() ) + { + if ( isRowHidden( it->parent()->indexOfChildItem( it ), d->mModel->index( it->parent(), 0 ) ) ) + setRowHidden( it->parent()->indexOfChildItem( it ), d->mModel->index( it->parent(), 0 ), false ); - QModelIndex idx = d->mModel->index( it, 0 ); + QModelIndex idx = d->mModel->index( it, 0 ); - Q_ASSERT( idx.isValid() ); - Q_ASSERT( static_cast< Item * >( idx.internalPointer() ) == it ); + Q_ASSERT( idx.isValid() ); + Q_ASSERT( static_cast< Item * >( idx.internalPointer() ) == it ); - if ( !isExpanded( idx ) ) - setExpanded( idx, true ); + if ( !isExpanded( idx ) ) + setExpanded( idx, true ); - it = it->parent(); - } + it = it->parent(); + } } bool View::isDisplayedWithParentsExpanded( Item * it ) const { - // An item is currently viewable iff - // - it is marked as viewable in the item structure (that is, qt knows about its existence) - // (and this means that all of its parents are marked as viewable) - // - it is not explicitly hidden - // - all of its parents are expanded + // An item is currently viewable iff + // - it is marked as viewable in the item structure (that is, qt knows about its existence) + // (and this means that all of its parents are marked as viewable) + // - it is not explicitly hidden + // - all of its parents are expanded - if ( !it ) - return false; // be nice and allow the caller not to care + if ( !it ) + return false; // be nice and allow the caller not to care - if ( !it->isViewable() ) - return false; // item not viewable (not attached to the viewable root or qt not yet aware of it) + if ( !it->isViewable() ) + return false; // item not viewable (not attached to the viewable root or qt not yet aware of it) - // the item and all the parents are marked as viewable. + // the item and all the parents are marked as viewable. - if ( isRowHidden( it->parent()->indexOfChildItem( it ), d->mModel->index( it->parent(), 0 ) ) ) - return false; // item qt representation explicitly hidden + if ( isRowHidden( it->parent()->indexOfChildItem( it ), d->mModel->index( it->parent(), 0 ) ) ) + return false; // item qt representation explicitly hidden - // the item (and theoretically all the parents) are not explicitly hidden + // the item (and theoretically all the parents) are not explicitly hidden - // check the parent chain + // check the parent chain - it = it->parent(); + it = it->parent(); - while ( it ) - { - if ( it == d->mModel->rootItem() ) - return true; // parent is root item: ok + while ( it ) + { + if ( it == d->mModel->rootItem() ) + return true; // parent is root item: ok - // parent is not root item + // parent is not root item - if ( !isExpanded( d->mModel->index( it, 0 ) ) ) - return false; // parent is not expanded (so child not actually visible) + if ( !isExpanded( d->mModel->index( it, 0 ) ) ) + return false; // parent is not expanded (so child not actually visible) - it = it->parent(); // climb up - } + it = it->parent(); // climb up + } - // parent hierarchy interrupted somewhere - return false; + // parent hierarchy interrupted somewhere + return false; } bool View::isThreaded() const { - if ( !d->mAggregation ) - return false; - return d->mAggregation->threading() != Aggregation::NoThreading; + if ( !d->mAggregation ) + return false; + return d->mAggregation->threading() != Aggregation::NoThreading; } void View::slotSelectionChanged( const QItemSelection &, const QItemSelection & ) { - // We assume that when selection changes, current item also changes. - QModelIndex current = currentIndex(); + // We assume that when selection changes, current item also changes. + QModelIndex current = currentIndex(); - if ( !current.isValid() ) - { - if ( d->mLastCurrentItem ) + if ( !current.isValid() ) { - d->mWidget->viewMessageSelected( 0 ); - d->mLastCurrentItem = 0; + if ( d->mLastCurrentItem ) + { + d->mWidget->viewMessageSelected( 0 ); + d->mLastCurrentItem = 0; + } + d->mWidget->viewMessageSelected( 0 ); + d->mWidget->viewSelectionChanged(); + return; } - d->mWidget->viewMessageSelected( 0 ); - d->mWidget->viewSelectionChanged(); - return; - } - if ( !selectionModel()->isSelected( current ) ) - { - if ( selectedIndexes().count() < 1 ) - { - // It may happen after row removals: Model calls this slot on currentIndex() - // that actually might have changed "silently", without being selected. - QItemSelection selection; - selection.append( QItemSelectionRange( current ) ); - selectionModel()->select( selection, QItemSelectionModel::Select | QItemSelectionModel::Rows ); - return; // the above recurses - } else { - // something is still selected anyway - // This is probably a result of CTRL+Click which unselected current: leave it as it is. - return; + if ( !selectionModel()->isSelected( current ) ) + { + if ( selectedIndexes().count() < 1 ) + { + // It may happen after row removals: Model calls this slot on currentIndex() + // that actually might have changed "silently", without being selected. + QItemSelection selection; + selection.append( QItemSelectionRange( current ) ); + selectionModel()->select( selection, QItemSelectionModel::Select | QItemSelectionModel::Rows ); + return; // the above recurses + } else { + // something is still selected anyway + // This is probably a result of CTRL+Click which unselected current: leave it as it is. + return; + } } - } - Item * it = static_cast< Item * >( current.internalPointer() ); - Q_ASSERT( it ); + Item * it = static_cast< Item * >( current.internalPointer() ); + Q_ASSERT( it ); - switch ( it->type() ) - { + switch ( it->type() ) + { case Item::Message: { - if ( d->mLastCurrentItem != it ) - { - kDebug() << "View message selected [" << static_cast< MessageItem * >( it )->subject() << "]"; - d->mWidget->viewMessageSelected( static_cast< MessageItem * >( it ) ); - d->mLastCurrentItem = it; - } + if ( d->mLastCurrentItem != it ) + { + kDebug() << "View message selected [" << static_cast< MessageItem * >( it )->subject() << "]"; + d->mWidget->viewMessageSelected( static_cast< MessageItem * >( it ) ); + d->mLastCurrentItem = it; + } } - break; + break; case Item::GroupHeader: - if ( d->mLastCurrentItem ) - { - d->mWidget->viewMessageSelected( 0 ); - d->mLastCurrentItem = 0; - } - break; + if ( d->mLastCurrentItem ) + { + d->mWidget->viewMessageSelected( 0 ); + d->mLastCurrentItem = 0; + } + break; default: - // should never happen - Q_ASSERT( false ); - break; - } + // should never happen + Q_ASSERT( false ); + break; + } - d->mWidget->viewSelectionChanged(); + d->mWidget->viewSelectionChanged(); } void View::mouseDoubleClickEvent( QMouseEvent * e ) { - // Perform a hit test - if ( !d->mDelegate->hitTest( e->pos(), true ) ) - return; - - // Something was hit :) - - Item * it = static_cast< Item * >( d->mDelegate->hitItem() ); - if ( !it ) - return; // should never happen + // Perform a hit test + if ( !d->mDelegate->hitTest( e->pos(), true ) ) + return; - switch ( it->type() ) - { + // Something was hit :) + + Item * it = static_cast< Item * >( d->mDelegate->hitItem() ); + if ( !it ) + return; // should never happen + + switch ( it->type() ) + { case Item::Message: { - // Let QTreeView handle the expansion - QTreeView::mousePressEvent( e ); + // Let QTreeView handle the expansion + QTreeView::mousePressEvent( e ); - switch ( e->button() ) - { + switch ( e->button() ) + { case Qt::LeftButton: - if ( d->mDelegate->hitContentItem() ) - { - // Double clikcking on clickable icons does NOT activate the message - if ( d->mDelegate->hitContentItem()->isIcon() && d->mDelegate->hitContentItem()->isClickable() ) - return; - } + if ( d->mDelegate->hitContentItem() ) + { + // Double clikcking on clickable icons does NOT activate the message + if ( d->mDelegate->hitContentItem()->isIcon() && d->mDelegate->hitContentItem()->isClickable() ) + return; + } - d->mWidget->viewMessageActivated( static_cast< MessageItem * >( it ) ); - break; + d->mWidget->viewMessageActivated( static_cast< MessageItem * >( it ) ); + break; default: - // make gcc happy - break; - } + // make gcc happy + break; + } } - break; + break; case Item::GroupHeader: { - // Don't let QTreeView handle the selection (as it deselects the curent messages) - switch ( e->button() ) - { + // Don't let QTreeView handle the selection (as it deselects the curent messages) + switch ( e->button() ) + { case Qt::LeftButton: - if ( it->childItemCount() > 0 ) - { - // toggle expanded state - setExpanded( d->mDelegate->hitIndex(), !isExpanded( d->mDelegate->hitIndex() ) ); - } - break; + if ( it->childItemCount() > 0 ) + { + // toggle expanded state + setExpanded( d->mDelegate->hitIndex(), !isExpanded( d->mDelegate->hitIndex() ) ); + } + break; default: - // make gcc happy - break; - } + // make gcc happy + break; + } } - break; + break; default: - // should never happen - Q_ASSERT( false ); - break; - } + // should never happen + Q_ASSERT( false ); + break; + } } void View::changeMessageStatusRead( MessageItem *it, bool read ) { - Akonadi::MessageStatus set = it->status(); - Akonadi::MessageStatus unset = it->status(); - if ( read ) { - set.setRead( true ); - unset.setRead( false ); - } else { - set.setRead( false ); - unset.setRead( true ); - } - viewport()->update(); + Akonadi::MessageStatus set = it->status(); + Akonadi::MessageStatus unset = it->status(); + if ( read ) { + set.setRead( true ); + unset.setRead( false ); + } else { + set.setRead( false ); + unset.setRead( true ); + } + viewport()->update(); - // This will actually request the widget to perform a status change on the storage. - // The request will be then processed by the Model and the message will be updated again. + // This will actually request the widget to perform a status change on the storage. + // The request will be then processed by the Model and the message will be updated again. - d->mWidget->viewMessageStatusChangeRequest( it, set, unset ); + d->mWidget->viewMessageStatusChangeRequest( it, set, unset ); } void View::changeMessageStatus( MessageItem * it, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &unset ) { - // We first change the status of MessageItem itself. This will make the change - // visible to the user even if the Model is actually in the middle of a long job (maybe it's loading) - // and can't process the status change request immediately. - // Here we actually desynchronize the cache and trust that the later call to - // d->mWidget->viewMessageStatusChangeRequest() will really perform the status change on the storage. - // Well... in KMail it will unless something is really screwed. Anyway, if it will not, at the next - // load the status will be just unchanged: no animals will be harmed. - - qint32 stat = it->status().toQInt32(); - stat |= set.toQInt32(); - stat &= ~( unset.toQInt32() ); - Akonadi::MessageStatus status; - status.fromQInt32( stat ); - it->setStatus( status ); + // We first change the status of MessageItem itself. This will make the change + // visible to the user even if the Model is actually in the middle of a long job (maybe it's loading) + // and can't process the status change request immediately. + // Here we actually desynchronize the cache and trust that the later call to + // d->mWidget->viewMessageStatusChangeRequest() will really perform the status change on the storage. + // Well... in KMail it will unless something is really screwed. Anyway, if it will not, at the next + // load the status will be just unchanged: no animals will be harmed. + + qint32 stat = it->status().toQInt32(); + stat |= set.toQInt32(); + stat &= ~( unset.toQInt32() ); + Akonadi::MessageStatus status; + status.fromQInt32( stat ); + it->setStatus( status ); - // Trigger an update so the immediate change will be shown to the user + // Trigger an update so the immediate change will be shown to the user - viewport()->update(); + viewport()->update(); - // This will actually request the widget to perform a status change on the storage. - // The request will be then processed by the Model and the message will be updated again. + // This will actually request the widget to perform a status change on the storage. + // The request will be then processed by the Model and the message will be updated again. - d->mWidget->viewMessageStatusChangeRequest( it, set, unset ); + d->mWidget->viewMessageStatusChangeRequest( it, set, unset ); } void View::mousePressEvent( QMouseEvent * e ) { - d->mMousePressPosition = QPoint(); + d->mMousePressPosition = QPoint(); - // Perform a hit test - if ( !d->mDelegate->hitTest( e->pos(), true ) ) - return; + // Perform a hit test + if ( !d->mDelegate->hitTest( e->pos(), true ) ) + return; - // Something was hit :) + // Something was hit :) - Item * it = static_cast< Item * >( d->mDelegate->hitItem() ); - if ( !it ) - return; // should never happen + Item * it = static_cast< Item * >( d->mDelegate->hitItem() ); + if ( !it ) + return; // should never happen - // Abort any pending message pre-selection as the user is probably - // already navigating the view (so pre-selection would make his view jump - // to an unexpected place). - d->mModel->setPreSelectionMode( PreSelectNone ); + // Abort any pending message pre-selection as the user is probably + // already navigating the view (so pre-selection would make his view jump + // to an unexpected place). + d->mModel->setPreSelectionMode( PreSelectNone ); - switch ( it->type() ) - { + switch ( it->type() ) + { case Item::Message: { - d->mMousePressPosition = e->pos(); + d->mMousePressPosition = e->pos(); - switch ( e->button() ) - { + switch ( e->button() ) + { case Qt::LeftButton: - // if we have multi selection then the meaning of hitting - // the content item is quite unclear. - if ( d->mDelegate->hitContentItem() && ( selectedIndexes().count() > 1 ) ) - { - kDebug() << "Left hit with selectedIndexes().count() == " << selectedIndexes().count(); - - switch ( d->mDelegate->hitContentItem()->type() ) - { - case Theme::ContentItem::AnnotationIcon: - static_cast< MessageItem * >( it )->editAnnotation(); - return; // don't select the item - break; - case Theme::ContentItem::ActionItemStateIcon: - changeMessageStatus( - static_cast< MessageItem * >( it ), - it->status().isToAct() ? Akonadi::MessageStatus() : Akonadi::MessageStatus::statusToAct(), - it->status().isToAct() ? Akonadi::MessageStatus::statusToAct() : Akonadi::MessageStatus() - ); - return; // don't select the item - break; - case Theme::ContentItem::ImportantStateIcon: - changeMessageStatus( - static_cast< MessageItem * >( it ), - it->status().isImportant() ? Akonadi::MessageStatus() : Akonadi::MessageStatus::statusImportant(), - it->status().isImportant() ? Akonadi::MessageStatus::statusImportant() : Akonadi::MessageStatus() - ); - return; // don't select the item - case Theme::ContentItem::ReadStateIcon: - changeMessageStatusRead( static_cast< MessageItem * >( it ), it->status().isRead() ? false : true ); - return; - break; - case Theme::ContentItem::SpamHamStateIcon: - changeMessageStatus( - static_cast< MessageItem * >( it ), - it->status().isSpam() ? Akonadi::MessageStatus() : ( it->status().isHam() ? Akonadi::MessageStatus::statusSpam() : Akonadi::MessageStatus::statusHam() ), - it->status().isSpam() ? Akonadi::MessageStatus::statusSpam() : ( it->status().isHam() ? Akonadi::MessageStatus::statusHam() : Akonadi::MessageStatus() ) - ); - return; // don't select the item - break; - case Theme::ContentItem::WatchedIgnoredStateIcon: - changeMessageStatus( - static_cast< MessageItem * >( it ), - it->status().isIgnored() ? Akonadi::MessageStatus() : ( it->status().isWatched() ? Akonadi::MessageStatus::statusIgnored() : Akonadi::MessageStatus::statusWatched() ), - it->status().isIgnored() ? Akonadi::MessageStatus::statusIgnored() : ( it->status().isWatched() ? Akonadi::MessageStatus::statusWatched() : Akonadi::MessageStatus() ) - ); - return; // don't select the item - break; - default: - // make gcc happy - break; + // if we have multi selection then the meaning of hitting + // the content item is quite unclear. + if ( d->mDelegate->hitContentItem() && ( selectedIndexes().count() > 1 ) ) + { + kDebug() << "Left hit with selectedIndexes().count() == " << selectedIndexes().count(); + + switch ( d->mDelegate->hitContentItem()->type() ) + { + case Theme::ContentItem::AnnotationIcon: + static_cast< MessageItem * >( it )->editAnnotation(); + return; // don't select the item + break; + case Theme::ContentItem::ActionItemStateIcon: + changeMessageStatus( + static_cast< MessageItem * >( it ), + it->status().isToAct() ? Akonadi::MessageStatus() : Akonadi::MessageStatus::statusToAct(), + it->status().isToAct() ? Akonadi::MessageStatus::statusToAct() : Akonadi::MessageStatus() + ); + return; // don't select the item + break; + case Theme::ContentItem::ImportantStateIcon: + changeMessageStatus( + static_cast< MessageItem * >( it ), + it->status().isImportant() ? Akonadi::MessageStatus() : Akonadi::MessageStatus::statusImportant(), + it->status().isImportant() ? Akonadi::MessageStatus::statusImportant() : Akonadi::MessageStatus() + ); + return; // don't select the item + case Theme::ContentItem::ReadStateIcon: + changeMessageStatusRead( static_cast< MessageItem * >( it ), it->status().isRead() ? false : true ); + return; + break; + case Theme::ContentItem::SpamHamStateIcon: + changeMessageStatus( + static_cast< MessageItem * >( it ), + it->status().isSpam() ? Akonadi::MessageStatus() : ( it->status().isHam() ? Akonadi::MessageStatus::statusSpam() : Akonadi::MessageStatus::statusHam() ), + it->status().isSpam() ? Akonadi::MessageStatus::statusSpam() : ( it->status().isHam() ? Akonadi::MessageStatus::statusHam() : Akonadi::MessageStatus() ) + ); + return; // don't select the item + break; + case Theme::ContentItem::WatchedIgnoredStateIcon: + changeMessageStatus( + static_cast< MessageItem * >( it ), + it->status().isIgnored() ? Akonadi::MessageStatus() : ( it->status().isWatched() ? Akonadi::MessageStatus::statusIgnored() : Akonadi::MessageStatus::statusWatched() ), + it->status().isIgnored() ? Akonadi::MessageStatus::statusIgnored() : ( it->status().isWatched() ? Akonadi::MessageStatus::statusWatched() : Akonadi::MessageStatus() ) + ); + return; // don't select the item + break; + default: + // make gcc happy + break; + } } - } - // Let QTreeView handle the selection and emit the appropriate signals (slotSelectionChanged() may be called) - QTreeView::mousePressEvent( e ); + // Let QTreeView handle the selection and emit the appropriate signals (slotSelectionChanged() may be called) + QTreeView::mousePressEvent( e ); - break; + break; case Qt::RightButton: - // Let QTreeView handle the selection and emit the appropriate signals (slotSelectionChanged() may be called) - QTreeView::mousePressEvent( e ); + // Let QTreeView handle the selection and emit the appropriate signals (slotSelectionChanged() may be called) + QTreeView::mousePressEvent( e ); - d->mWidget->viewMessageListContextPopupRequest( selectionAsMessageItemList(), viewport()->mapToGlobal( e->pos() ) ); - break; + d->mWidget->viewMessageListContextPopupRequest( selectionAsMessageItemList(), viewport()->mapToGlobal( e->pos() ) ); + break; default: - // make gcc happy - break; - } + // make gcc happy + break; + } } - break; + break; case Item::GroupHeader: { - // Don't let QTreeView handle the selection (as it deselects the curent messages) - GroupHeaderItem *groupHeaderItem = static_cast< GroupHeaderItem * >( it ); + // Don't let QTreeView handle the selection (as it deselects the curent messages) + GroupHeaderItem *groupHeaderItem = static_cast< GroupHeaderItem * >( it ); - switch ( e->button() ) - { + switch ( e->button() ) + { case Qt::LeftButton: - { + { QModelIndex index = d->mModel->index( groupHeaderItem, 0 ); if ( index.isValid() ) - setCurrentIndex( index ); + setCurrentIndex( index ); if ( !d->mDelegate->hitContentItem() ) - return; + return; if ( d->mDelegate->hitContentItem()->type() == Theme::ContentItem::ExpandedStateIcon ) { - if ( groupHeaderItem->childItemCount() > 0 ) - { - // toggle expanded state - setExpanded( d->mDelegate->hitIndex(), !isExpanded( d->mDelegate->hitIndex() ) ); - } + if ( groupHeaderItem->childItemCount() > 0 ) + { + // toggle expanded state + setExpanded( d->mDelegate->hitIndex(), !isExpanded( d->mDelegate->hitIndex() ) ); + } } - } - break; + } + break; case Qt::RightButton: - d->mWidget->viewGroupHeaderContextPopupRequest( groupHeaderItem, viewport()->mapToGlobal( e->pos() ) ); - break; + d->mWidget->viewGroupHeaderContextPopupRequest( groupHeaderItem, viewport()->mapToGlobal( e->pos() ) ); + break; default: - // make gcc happy - break; - } + // make gcc happy + break; + } } - break; + break; default: - // should never happen - Q_ASSERT( false ); - break; - } + // should never happen + Q_ASSERT( false ); + break; + } } void View::mouseMoveEvent( QMouseEvent * e ) { - if ( !e->buttons() & Qt::LeftButton ) - { - QTreeView::mouseMoveEvent( e ); - return; - } + if ( !e->buttons() & Qt::LeftButton ) + { + QTreeView::mouseMoveEvent( e ); + return; + } - if ( d->mMousePressPosition.isNull() ) - return; + if ( d->mMousePressPosition.isNull() ) + return; - if ( ( e->pos() - d->mMousePressPosition ).manhattanLength() <= KGlobalSettings::dndEventDelay() ) - return; + if ( ( e->pos() - d->mMousePressPosition ).manhattanLength() <= KGlobalSettings::dndEventDelay() ) + return; - d->mWidget->viewStartDragRequest(); + d->mWidget->viewStartDragRequest(); } void View::contextMenuEvent( QContextMenuEvent * e ) { - Q_UNUSED( e ); - QModelIndex index = currentIndex(); - if ( index.isValid() ) { - QRect indexRect = this->visualRect( index ); - QPoint pos; - - if ( ( indexRect.isValid() ) && ( indexRect.bottom() > 0 ) ) { - if ( indexRect.bottom() > viewport()->height() ) { - if ( indexRect.top() <= viewport()->height() ) { - pos = indexRect.topLeft(); - } - } else { - pos = indexRect.bottomLeft(); - } - } - - Item *item = static_cast< Item * >( index.internalPointer() ); - if ( item ) { - if ( item->type() == Item::GroupHeader ) - d->mWidget->viewGroupHeaderContextPopupRequest( static_cast< GroupHeaderItem * >( item ), viewport()->mapToGlobal( pos ) ); - else if ( !selectionEmpty() ) - d->mWidget->viewMessageListContextPopupRequest( selectionAsMessageItemList(), viewport()->mapToGlobal( pos ) ); + Q_UNUSED( e ); + QModelIndex index = currentIndex(); + if ( index.isValid() ) { + QRect indexRect = this->visualRect( index ); + QPoint pos; + + if ( ( indexRect.isValid() ) && ( indexRect.bottom() > 0 ) ) { + if ( indexRect.bottom() > viewport()->height() ) { + if ( indexRect.top() <= viewport()->height() ) { + pos = indexRect.topLeft(); + } + } else { + pos = indexRect.bottomLeft(); + } + } + + Item *item = static_cast< Item * >( index.internalPointer() ); + if ( item ) { + if ( item->type() == Item::GroupHeader ) + d->mWidget->viewGroupHeaderContextPopupRequest( static_cast< GroupHeaderItem * >( item ), viewport()->mapToGlobal( pos ) ); + else if ( !selectionEmpty() ) + d->mWidget->viewMessageListContextPopupRequest( selectionAsMessageItemList(), viewport()->mapToGlobal( pos ) ); + } } - } } void View::dragEnterEvent( QDragEnterEvent * e ) { - d->mWidget->viewDragEnterEvent( e ); + d->mWidget->viewDragEnterEvent( e ); } void View::dragMoveEvent( QDragMoveEvent * e ) { - d->mWidget->viewDragMoveEvent( e ); + d->mWidget->viewDragMoveEvent( e ); } void View::dropEvent( QDropEvent * e ) { - d->mWidget->viewDropEvent( e ); + d->mWidget->viewDropEvent( e ); } void View::changeEvent( QEvent *e ) { - switch ( e->type() ) - { + switch ( e->type() ) + { case QEvent::PaletteChange: case QEvent::FontChange: case QEvent::StyleChange: case QEvent::LayoutDirectionChange: case QEvent::LocaleChange: case QEvent::LanguageChange: - // All of these affect the theme's internal cache. - setTheme( d->mTheme ); - // A layoutChanged() event will screw up the view state a bit. - // Since this is a rare event we just reload the view. - reload(); - break; + // All of these affect the theme's internal cache. + setTheme( d->mTheme ); + // A layoutChanged() event will screw up the view state a bit. + // Since this is a rare event we just reload the view. + reload(); + break; default: - // make gcc happy by default - break; - } + // make gcc happy by default + break; + } - QTreeView::changeEvent( e ); + QTreeView::changeEvent( e ); } bool View::event( QEvent *e ) { - // We catch ToolTip events and pass everything else + // We catch ToolTip events and pass everything else - if( e->type() != QEvent::ToolTip ) - return QTreeView::event( e ); + if( e->type() != QEvent::ToolTip ) + return QTreeView::event( e ); - if ( !Settings::self()->messageToolTipEnabled() ) - return true; // don't display tooltips + if ( !Settings::self()->messageToolTipEnabled() ) + return true; // don't display tooltips - QHelpEvent * he = dynamic_cast< QHelpEvent * >( e ); - if ( !he ) - return true; // eh ? + QHelpEvent * he = dynamic_cast< QHelpEvent * >( e ); + if ( !he ) + return true; // eh ? - QPoint pnt = viewport()->mapFromGlobal( mapToGlobal( he->pos() ) ); + QPoint pnt = viewport()->mapFromGlobal( mapToGlobal( he->pos() ) ); - if ( pnt.y() < 0 ) - return true; // don't display the tooltip for items hidden under the header + if ( pnt.y() < 0 ) + return true; // don't display the tooltip for items hidden under the header - QModelIndex idx = indexAt( pnt ); - if ( !idx.isValid() ) - return true; // may be + QModelIndex idx = indexAt( pnt ); + if ( !idx.isValid() ) + return true; // may be - Item * it = static_cast< Item * >( idx.internalPointer() ); - if ( !it ) - return true; // hum + Item * it = static_cast< Item * >( idx.internalPointer() ); + if ( !it ) + return true; // hum - Q_ASSERT( storageModel() ); + Q_ASSERT( storageModel() ); - QColor bckColor = palette().color( QPalette::ToolTipBase ); - QColor txtColor = palette().color( QPalette::ToolTipText ); - QColor darkerColor( - ( ( bckColor.red() * 8 ) + ( txtColor.red() * 2 ) ) / 10, - ( ( bckColor.green() * 8 ) + ( txtColor.green() * 2 ) ) / 10, - ( ( bckColor.blue() * 8 ) + ( txtColor.blue() * 2 ) ) / 10 - ); + QColor bckColor = palette().color( QPalette::ToolTipBase ); + QColor txtColor = palette().color( QPalette::ToolTipText ); + QColor darkerColor( + ( ( bckColor.red() * 8 ) + ( txtColor.red() * 2 ) ) / 10, + ( ( bckColor.green() * 8 ) + ( txtColor.green() * 2 ) ) / 10, + ( ( bckColor.blue() * 8 ) + ( txtColor.blue() * 2 ) ) / 10 + ); - QString bckColorName = bckColor.name(); - QString txtColorName = txtColor.name(); - QString darkerColorName = darkerColor.name(); - const bool textIsLeftToRight = ( QApplication::layoutDirection() == Qt::LeftToRight ); - const QString textDirection = textIsLeftToRight ? QLatin1String( "left" ) : QLatin1String( "right" ); + QString bckColorName = bckColor.name(); + QString txtColorName = txtColor.name(); + QString darkerColorName = darkerColor.name(); + const bool textIsLeftToRight = ( QApplication::layoutDirection() == Qt::LeftToRight ); + const QString textDirection = textIsLeftToRight ? QLatin1String( "left" ) : QLatin1String( "right" ); - QString tip = QString::fromLatin1( - "" - ); + QString tip = QString::fromLatin1( + "
" + ); - switch ( it->type() ) - { + switch ( it->type() ) + { case Item::Message: { - MessageItem *mi = static_cast< MessageItem * >( it ); + MessageItem *mi = static_cast< MessageItem * >( it ); - tip += QString::fromLatin1( - "" \ - "" \ - "" - ).arg( txtColorName ).arg( bckColorName ).arg( Qt::escape( mi->subject() ) ).arg( textDirection ); - - tip += QString::fromLatin1( - "" \ - "
" \ - "
" \ - "%3" \ - "
" \ - "
" \ - "" - ); + tip += QString::fromLatin1( + "" \ + "" \ + "" + ).arg( txtColorName ).arg( bckColorName ).arg( Qt::escape( mi->subject() ) ).arg( textDirection ); + + tip += QString::fromLatin1( + "" \ + "
" \ + "
" \ + "%3" \ + "
" \ + "
" \ + "" + ); + + const QString htmlCodeForStandardRow = QString::fromLatin1( + "" \ + "" \ + "" \ + "" ); - const QString htmlCodeForStandardRow = QString::fromLatin1( - "" \ - "" \ - "" \ - "" ); - - - if ( textIsLeftToRight ) { - tip += htmlCodeForStandardRow.arg( i18n( "From" ) ).arg( MessageCore::StringUtil::stripEmailAddr( mi->sender() ) ); - tip += htmlCodeForStandardRow.arg( i18nc( "Receiver of the email", "To" ) ).arg( MessageCore::StringUtil::stripEmailAddr( mi->receiver() ) ); - tip += htmlCodeForStandardRow.arg( i18n( "Date" ) ).arg( mi->formattedDate() ); - } else { - tip += htmlCodeForStandardRow.arg( MessageCore::StringUtil::stripEmailAddr( mi->sender() ) ).arg( i18n( "From" ) ); - tip += htmlCodeForStandardRow.arg( MessageCore::StringUtil::stripEmailAddr( mi->receiver() ) ).arg( i18nc( "Receiver of the email", "To" ) ); - tip += htmlCodeForStandardRow.arg( mi->formattedDate() ).arg( i18n( "Date" ) ); - } - - QString status = mi->statusDescription(); - const QString tags = mi->tagListDescription(); - if ( !tags.isEmpty () ) - { - if ( !status.isEmpty() ) - status += QLatin1String( ", " ); - status += tags; - } - - if ( textIsLeftToRight ) { - tip += htmlCodeForStandardRow.arg( i18n( "Status" ) ).arg( status ); - tip += htmlCodeForStandardRow.arg( i18n( "Size" ) ).arg( mi->formattedSize() ); - } else { - tip += htmlCodeForStandardRow.arg( status ).arg( i18n( "Status" ) ); - tip += htmlCodeForStandardRow.arg( mi->formattedSize() ).arg( i18n( "Size" ) ); - } - if ( mi->hasAnnotation() ) { if ( textIsLeftToRight ) { - tip += htmlCodeForStandardRow.arg( i18n( "Note" ) ).arg( mi->annotation().replace( QLatin1Char( '\n' ), QLatin1String( "
" ) ) ); + tip += htmlCodeForStandardRow.arg( i18n( "From" ) ).arg( MessageCore::StringUtil::stripEmailAddr( mi->sender() ) ); + tip += htmlCodeForStandardRow.arg( i18nc( "Receiver of the email", "To" ) ).arg( MessageCore::StringUtil::stripEmailAddr( mi->receiver() ) ); + tip += htmlCodeForStandardRow.arg( i18n( "Date" ) ).arg( mi->formattedDate() ); } else { - tip += htmlCodeForStandardRow.arg( mi->annotation().replace( QLatin1Char( '\n' ), QLatin1String( "
" ) ) ).arg( i18n( "Note" ) ); + tip += htmlCodeForStandardRow.arg( MessageCore::StringUtil::stripEmailAddr( mi->sender() ) ).arg( i18n( "From" ) ); + tip += htmlCodeForStandardRow.arg( MessageCore::StringUtil::stripEmailAddr( mi->receiver() ) ).arg( i18nc( "Receiver of the email", "To" ) ); + tip += htmlCodeForStandardRow.arg( mi->formattedDate() ).arg( i18n( "Date" ) ); + } + + QString status = mi->statusDescription(); + const QString tags = mi->tagListDescription(); + if ( !tags.isEmpty () ) + { + if ( !status.isEmpty() ) + status += QLatin1String( ", " ); + status += tags; } - } - QString content = MessageList::Util::contentSummary( mi->akonadiItem() ); - if ( !content.trimmed().isEmpty() ) { if ( textIsLeftToRight ) { - tip += htmlCodeForStandardRow.arg( i18n( "Preview" ) ).arg( content.replace( QLatin1Char( '\n' ), QLatin1String( "
" ) ) ); + tip += htmlCodeForStandardRow.arg( i18n( "Status" ) ).arg( status ); + tip += htmlCodeForStandardRow.arg( i18n( "Size" ) ).arg( mi->formattedSize() ); } else { - tip += htmlCodeForStandardRow.arg( content.replace( QLatin1Char( '\n' ), QLatin1String( "
" ) ) ).arg( i18n( "Preview" ) ); + tip += htmlCodeForStandardRow.arg( status ).arg( i18n( "Status" ) ); + tip += htmlCodeForStandardRow.arg( mi->formattedSize() ).arg( i18n( "Size" ) ); } - } - tip += QString::fromLatin1( - "" \ - "" - ); - - // FIXME: Find a way to show also CC and other header fields ? - - if ( mi->hasChildren() ) - { - Item::ChildItemStats stats; - mi->childItemStats( stats ); - - QString statsText; - - statsText = i18np( "%1 reply", "%1 replies", mi->childItemCount() ); - statsText += QLatin1String( ", " ); - - statsText += i18np( - "%1 message in subtree (%2 unread)", - "%1 messages in subtree (%2 unread)", - stats.mTotalChildCount, - stats.mUnreadChildCount - ); + if ( mi->hasAnnotation() ) { + if ( textIsLeftToRight ) { + tip += htmlCodeForStandardRow.arg( i18n( "Note" ) ).arg( mi->annotation().replace( QLatin1Char( '\n' ), QLatin1String( "
" ) ) ); + } else { + tip += htmlCodeForStandardRow.arg( mi->annotation().replace( QLatin1Char( '\n' ), QLatin1String( "
" ) ) ).arg( i18n( "Note" ) ); + } + } + QString content = MessageList::Util::contentSummary( mi->akonadiItem() ); + if ( !content.trimmed().isEmpty() ) { + if ( textIsLeftToRight ) { + tip += htmlCodeForStandardRow.arg( i18n( "Preview" ) ).arg( content.replace( QLatin1Char( '\n' ), QLatin1String( "
" ) ) ); + } else { + tip += htmlCodeForStandardRow.arg( content.replace( QLatin1Char( '\n' ), QLatin1String( "
" ) ) ).arg( i18n( "Preview" ) ); + } + } tip += QString::fromLatin1( - "" \ - "" \ - "" - ).arg( darkerColorName ).arg( statsText ).arg( textDirection ); - } + "" \ + "" + ); + + // FIXME: Find a way to show also CC and other header fields ? + + if ( mi->hasChildren() ) + { + Item::ChildItemStats stats; + mi->childItemStats( stats ); + + QString statsText; + + statsText = i18np( "%1 reply", "%1 replies", mi->childItemCount() ); + statsText += QLatin1String( ", " ); + + statsText += i18np( + "%1 message in subtree (%2 unread)", + "%1 messages in subtree (%2 unread)", + stats.mTotalChildCount, + stats.mUnreadChildCount + ); + + + tip += QString::fromLatin1( + "" \ + "" \ + "" + ).arg( darkerColorName ).arg( statsText ).arg( textDirection ); + } } - break; + break; case Item::GroupHeader: { - GroupHeaderItem *ghi = static_cast< GroupHeaderItem * >( it ); + GroupHeaderItem *ghi = static_cast< GroupHeaderItem * >( it ); - tip += QString::fromLatin1( - "" \ - "" \ - "" - ).arg( txtColorName ).arg( bckColorName ).arg( ghi->label() ).arg( textDirection ); + tip += QString::fromLatin1( + "" \ + "" \ + "" + ).arg( txtColorName ).arg( bckColorName ).arg( ghi->label() ).arg( textDirection ); - QString description; + QString description; - switch( d->mAggregation->grouping() ) - { + switch( d->mAggregation->grouping() ) + { case Aggregation::GroupByDate: - if ( d->mAggregation->threading() != Aggregation::NoThreading ) - { - switch ( d->mAggregation->threadLeader() ) + if ( d->mAggregation->threading() != Aggregation::NoThreading ) { - case Aggregation::TopmostMessage: - if ( ghi->label().contains( QRegExp( QLatin1String( "[0-9]" ) ) ) ) - description = i18nc( - "@info:tooltip Formats to something like 'Threads started on 2008-12-21'", - "Threads started on %1", - ghi->label() - ); - else - description = i18nc( - "@info:tooltip Formats to something like 'Threads started Yesterday'", - "Threads started %1", - ghi->label() - ); - break; - case Aggregation::MostRecentMessage: - description = i18n( "Threads with messages dated %1", ghi->label() ); - break; - default: - // nuthin, make gcc happy - break; - } - } else { - if ( ghi->label().contains( QRegExp( QLatin1String( "[0-9]" ) ) ) ) - { - if ( storageModel()->containsOutboundMessages() ) - description = i18nc( - "@info:tooltip Formats to something like 'Messages sent on 2008-12-21'", - "Messages sent on %1", - ghi->label() - ); - else - description = i18nc( - "@info:tooltip Formats to something like 'Messages received on 2008-12-21'", - "Messages received on %1", - ghi->label() - ); + switch ( d->mAggregation->threadLeader() ) + { + case Aggregation::TopmostMessage: + if ( ghi->label().contains( QRegExp( QLatin1String( "[0-9]" ) ) ) ) + description = i18nc( + "@info:tooltip Formats to something like 'Threads started on 2008-12-21'", + "Threads started on %1", + ghi->label() + ); + else + description = i18nc( + "@info:tooltip Formats to something like 'Threads started Yesterday'", + "Threads started %1", + ghi->label() + ); + break; + case Aggregation::MostRecentMessage: + description = i18n( "Threads with messages dated %1", ghi->label() ); + break; + default: + // nuthin, make gcc happy + break; + } } else { - if ( storageModel()->containsOutboundMessages() ) - description = i18nc( - "@info:tooltip Formats to something like 'Messages sent Yesterday'", - "Messages sent %1", - ghi->label() - ); - else - description = i18nc( - "@info:tooltip Formats to something like 'Messages received Yesterday'", - "Messages received %1", - ghi->label() - ); + if ( ghi->label().contains( QRegExp( QLatin1String( "[0-9]" ) ) ) ) + { + if ( storageModel()->containsOutboundMessages() ) + description = i18nc( + "@info:tooltip Formats to something like 'Messages sent on 2008-12-21'", + "Messages sent on %1", + ghi->label() + ); + else + description = i18nc( + "@info:tooltip Formats to something like 'Messages received on 2008-12-21'", + "Messages received on %1", + ghi->label() + ); + } else { + if ( storageModel()->containsOutboundMessages() ) + description = i18nc( + "@info:tooltip Formats to something like 'Messages sent Yesterday'", + "Messages sent %1", + ghi->label() + ); + else + description = i18nc( + "@info:tooltip Formats to something like 'Messages received Yesterday'", + "Messages received %1", + ghi->label() + ); + } } - } - break; + break; case Aggregation::GroupByDateRange: - if ( d->mAggregation->threading() != Aggregation::NoThreading ) - { - switch ( d->mAggregation->threadLeader() ) - { - case Aggregation::TopmostMessage: - description = i18n( "Threads started within %1", ghi->label() ); - break; - case Aggregation::MostRecentMessage: - description = i18n( "Threads containing messages with dates within %1", ghi->label() ); - break; - default: - // nuthin, make gcc happy - break; - } - } else { - if ( storageModel()->containsOutboundMessages() ) - description = i18n( "Messages sent within %1", ghi->label() ); - else - description = i18n( "Messages received within %1", ghi->label() ); - } - break; + if ( d->mAggregation->threading() != Aggregation::NoThreading ) + { + switch ( d->mAggregation->threadLeader() ) + { + case Aggregation::TopmostMessage: + description = i18n( "Threads started within %1", ghi->label() ); + break; + case Aggregation::MostRecentMessage: + description = i18n( "Threads containing messages with dates within %1", ghi->label() ); + break; + default: + // nuthin, make gcc happy + break; + } + } else { + if ( storageModel()->containsOutboundMessages() ) + description = i18n( "Messages sent within %1", ghi->label() ); + else + description = i18n( "Messages received within %1", ghi->label() ); + } + break; case Aggregation::GroupBySenderOrReceiver: case Aggregation::GroupBySender: - if ( d->mAggregation->threading() != Aggregation::NoThreading ) - { - switch ( d->mAggregation->threadLeader() ) - { - case Aggregation::TopmostMessage: - description = i18n( "Threads started by %1", ghi->label() ); - break; - case Aggregation::MostRecentMessage: - description = i18n( "Threads with most recent message by %1", ghi->label() ); - break; - default: - // nuthin, make gcc happy - break; - } - } else { - if ( storageModel()->containsOutboundMessages() ) - { - if ( d->mAggregation->grouping() == Aggregation::GroupBySenderOrReceiver ) - description = i18n( "Messages sent to %1", ghi->label() ); - else - description = i18n( "Messages sent by %1", ghi->label() ); + if ( d->mAggregation->threading() != Aggregation::NoThreading ) + { + switch ( d->mAggregation->threadLeader() ) + { + case Aggregation::TopmostMessage: + description = i18n( "Threads started by %1", ghi->label() ); + break; + case Aggregation::MostRecentMessage: + description = i18n( "Threads with most recent message by %1", ghi->label() ); + break; + default: + // nuthin, make gcc happy + break; + } } else { - description = i18n( "Messages received from %1", ghi->label() ); + if ( storageModel()->containsOutboundMessages() ) + { + if ( d->mAggregation->grouping() == Aggregation::GroupBySenderOrReceiver ) + description = i18n( "Messages sent to %1", ghi->label() ); + else + description = i18n( "Messages sent by %1", ghi->label() ); + } else { + description = i18n( "Messages received from %1", ghi->label() ); + } } - } - break; + break; case Aggregation::GroupByReceiver: - if ( d->mAggregation->threading() != Aggregation::NoThreading ) - { - switch ( d->mAggregation->threadLeader() ) - { - case Aggregation::TopmostMessage: - description = i18n( "Threads directed to %1", ghi->label() ); - break; - case Aggregation::MostRecentMessage: - description = i18n( "Threads with most recent message directed to %1", ghi->label() ); - break; - default: - // nuthin, make gcc happy - break; - } - } else { - if ( storageModel()->containsOutboundMessages() ) + if ( d->mAggregation->threading() != Aggregation::NoThreading ) { - description = i18n( "Messages sent to %1", ghi->label() ); + switch ( d->mAggregation->threadLeader() ) + { + case Aggregation::TopmostMessage: + description = i18n( "Threads directed to %1", ghi->label() ); + break; + case Aggregation::MostRecentMessage: + description = i18n( "Threads with most recent message directed to %1", ghi->label() ); + break; + default: + // nuthin, make gcc happy + break; + } } else { - description = i18n( "Messages received by %1", ghi->label() ); + if ( storageModel()->containsOutboundMessages() ) + { + description = i18n( "Messages sent to %1", ghi->label() ); + } else { + description = i18n( "Messages received by %1", ghi->label() ); + } } - } - break; + break; default: - // nuthin, make gcc happy - break; - } + // nuthin, make gcc happy + break; + } - if ( !description.isEmpty() ) - { - tip += QString::fromLatin1( - "" \ - "" \ - "" - ).arg( description ).arg( textDirection ); - } - - if ( ghi->hasChildren() ) - { - Item::ChildItemStats stats; - ghi->childItemStats( stats ); - - QString statsText; - - if ( d->mAggregation->threading() != Aggregation::NoThreading ) - { - statsText = i18np( "%1 thread", "%1 threads", ghi->childItemCount() ); - statsText += QLatin1String( ", " ); - } - - statsText += i18np( - "%1 message (%2 unread)", - "%1 messages (%2 unread)", - stats.mTotalChildCount, - stats.mUnreadChildCount - ); + if ( !description.isEmpty() ) + { + tip += QString::fromLatin1( + "" \ + "" \ + "" + ).arg( description ).arg( textDirection ); + } - tip += QString::fromLatin1( - "" \ - "" \ - "" - ).arg( darkerColorName ).arg( statsText ).arg( textDirection ); - } + if ( ghi->hasChildren() ) + { + Item::ChildItemStats stats; + ghi->childItemStats( stats ); + + QString statsText; + + if ( d->mAggregation->threading() != Aggregation::NoThreading ) + { + statsText = i18np( "%1 thread", "%1 threads", ghi->childItemCount() ); + statsText += QLatin1String( ", " ); + } + + statsText += i18np( + "%1 message (%2 unread)", + "%1 messages (%2 unread)", + stats.mTotalChildCount, + stats.mUnreadChildCount + ); + + tip += QString::fromLatin1( + "" \ + "" \ + "" + ).arg( darkerColorName ).arg( statsText ).arg( textDirection ); + } } - break; + break; default: - // nuthin (just make gcc happy for now) - break; - } + // nuthin (just make gcc happy for now) + break; + } - tip += QString::fromLatin1( - "
" \ + "
" \ + "%1:" \ + "
" \ + "
" \ + "%2" \ + "
" \ - "
" \ - "%1:" \ - "
" \ - "
" \ - "%2" \ - "
" \ - "%2" \ - "
" \ + "%2" \ + "
" \ - "
" \ - "%3" \ - "
" \ - "
" \ + "
" \ + "%3" \ + "
" \ + "
" \ - "%1" \ - "
" \ + "%1" \ + "
" \ - "%2" \ - "
" \ + "%2" \ + "
" - ); + tip += QString::fromLatin1( + "
" + ); - QToolTip::showText( he->globalPos(), tip, viewport(), visualRect( idx ) ); + QToolTip::showText( he->globalPos(), tip, viewport(), visualRect( idx ) ); - return true; + return true; } void View::slotCollapseAllGroups() { - setAllGroupsExpanded( false ); + setAllGroupsExpanded( false ); } void View::slotExpandAllGroups() { - setAllGroupsExpanded( true ); + setAllGroupsExpanded( true ); } void View::slotCollapseCurrentItem() { - setCurrentThreadExpanded( false ); + setCurrentThreadExpanded( false ); } void View::slotExpandCurrentItem() { - setCurrentThreadExpanded( true ); + setCurrentThreadExpanded( true ); } void View::focusQuickSearch() { - d->mWidget->focusQuickSearch(); + d->mWidget->focusQuickSearch(); } QList View::currentFilterStatus() const { - return d->mWidget->currentFilterStatus(); + return d->mWidget->currentFilterStatus(); } QString View::currentFilterSearchString() const { - return d->mWidget->currentFilterSearchString(); + return d->mWidget->currentFilterSearchString(); } void View::setRowHidden( int row, const QModelIndex & parent, bool hide ) { - const QModelIndex rowModelIndex = model()->index( row, 0, parent ); - const Item* const rowItem = static_cast< Item * >( rowModelIndex.internalPointer() ); + const QModelIndex rowModelIndex = model()->index( row, 0, parent ); + const Item* const rowItem = static_cast< Item * >( rowModelIndex.internalPointer() ); - if ( rowItem ) { - const bool currentlyHidden = isRowHidden( row, parent ); + if ( rowItem ) { + const bool currentlyHidden = isRowHidden( row, parent ); - if ( currentlyHidden != hide ) { - if ( currentMessageItem() == rowItem ) { - selectionModel()->clear(); - selectionModel()->clearSelection(); - } + if ( currentlyHidden != hide ) { + if ( currentMessageItem() == rowItem ) { + selectionModel()->clear(); + selectionModel()->clearSelection(); + } + } } - } - QTreeView::setRowHidden( row, parent, hide ); + QTreeView::setRowHidden( row, parent, hide ); } void View::sortOrderMenuAboutToShow(KMenu *menu) { - d->mWidget->sortOrderMenuAboutToShow(menu); + d->mWidget->sortOrderMenuAboutToShow(menu); } void View::aggregationMenuAboutToShow(KMenu *menu) { - d->mWidget->aggregationMenuAboutToShow(menu); + d->mWidget->aggregationMenuAboutToShow(menu); } void View::themeMenuAboutToShow(KMenu *menu) { - d->mWidget->themeMenuAboutToShow(menu); + d->mWidget->themeMenuAboutToShow(menu); } void View::setCollapseItem(const QModelIndex& index) { if(index.isValid()) - setExpanded( index, false ); + setExpanded( index, false ); } void View::setExpandItem(const QModelIndex& index) { if(index.isValid()) - setExpanded( index, true ); + setExpanded( index, true ); } void View::setQuickSearchClickMessage(const QString &msg) diff -Nru kdepim-4.12.97/messagelist/core/view.h kdepim-4.13.0/messagelist/core/view.h --- kdepim-4.12.97/messagelist/core/view.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/view.h 2014-04-10 07:40:20.000000000 +0000 @@ -34,7 +34,7 @@ namespace Akonadi { - class MessageStatus; +class MessageStatus; } namespace MessageList @@ -63,26 +63,26 @@ */ class MESSAGELIST_EXPORT View : public QTreeView { - friend class Model; - friend class ModelPrivate; - Q_OBJECT + friend class Model; + friend class ModelPrivate; + Q_OBJECT public: - explicit View( Widget *parent ); - ~View(); + explicit View( Widget *parent ); + ~View(); - /** + /** * Returns the Model attacched to this View. You probably never need to manipulate * it directly. */ - Model * model() const; + Model * model() const; - /** + /** * Returns the Delegate attacched to this View. You probably never need to manipulate * it directly. Model uses it to obtain size hints. */ - Delegate * delegate() const; + Delegate * delegate() const; - /** + /** * Sets the StorageModel to be displayed in this view. The StorageModel may be 0 (so no content is displayed). * Setting the StorageModel will obviously trigger a view reload. * Be sure to set the Aggregation and the Theme BEFORE calling this function. @@ -90,72 +90,72 @@ * Pre-selection is the action of automatically selecting a message just after the folder * has finished loading. See Model::setStorageModel() for more information. */ - void setStorageModel( StorageModel * storageModel, PreSelectionMode preSelectionMode = PreSelectLastSelected ); + void setStorageModel( StorageModel * storageModel, PreSelectionMode preSelectionMode = PreSelectLastSelected ); - /** + /** * Returns the currently displayed StorageModel. May be 0. */ - StorageModel * storageModel() const; + StorageModel * storageModel() const; - /** + /** * Sets the aggregation for this view. * Does not trigger a reload of the view: you *MUST* trigger it manually. */ - void setAggregation( const Aggregation * aggregation ); + void setAggregation( const Aggregation * aggregation ); - /** + /** * Sets the specified theme for this view. * Does not trigger a reload of the view: you *MUST* trigger it manually. */ - void setTheme( Theme * theme ); + void setTheme( Theme * theme ); - /** + /** * Sets the specified sort order. * Does not trigger a reload of the view: you *MUST* trigger it manually. */ - void setSortOrder( const SortOrder * sortOrder ); + void setSortOrder( const SortOrder * sortOrder ); - /** + /** * Triggers a reload of the view in order to re-display the current folder. * Call this function after changing the Aggregation or the Theme. */ - void reload(); + void reload(); - /** + /** * Returns the current MessageItem (that is bound to current StorageModel). * May return 0 if there is no current message or no current StorageModel. * If the current message item isn't currently selected (so is only focused) * then it's selected when this function is called, unless selectIfNeeded is false. */ - MessageItem * currentMessageItem( bool selectIfNeeded = true ) const; + MessageItem * currentMessageItem( bool selectIfNeeded = true ) const; - /** + /** * Returns the current Item (that is bound to current StorageModel). * May return 0 if there is no current item or no current StorageModel. * If the current item isn't currently selected (so is only focused) * then it's selected when this function is called. */ - Item * currentItem() const; + Item * currentItem() const; - /** + /** * Sets the current message item. */ - void setCurrentMessageItem( MessageItem * it, bool center = false ); + void setCurrentMessageItem( MessageItem * it, bool center = false ); - /** + /** * Returns true if the specified item is currently displayed in the tree * and has all the parents expanded. This means that the user can * see the message (by eventually scrolling the view). */ - bool isDisplayedWithParentsExpanded( Item * it ) const; + bool isDisplayedWithParentsExpanded( Item * it ) const; - /** + /** * Makes sure that the specified is currently viewable by the user. * This means that the user can see the message (by eventually scrolling the view). */ - void ensureDisplayedWithParentsExpanded( Item * it ); + void ensureDisplayedWithParentsExpanded( Item * it ); - /** + /** * Returns the currently selected MessageItems (bound to current StorageModel). * The list may be empty if there are no selected messages or no StorageModel. * @@ -166,9 +166,9 @@ * to the main even loop. Don't store it for any longer. If you need to reference * this set of messages at a later stage then take a look at createPersistentSet(). */ - QList< MessageItem * > selectionAsMessageItemList( bool includeCollapsedChildren = true ) const; + QList< MessageItem * > selectionAsMessageItemList( bool includeCollapsedChildren = true ) const; - /** + /** * Returns the MessageItems bound to the current StorageModel that * are part of the current thread. The current thread is the thread * that contains currentMessageItem(). @@ -178,20 +178,20 @@ * to the main even loop. Don't store it for any longer. If you need to reference * this set of messages at a later stage then take a look at createPersistentSet(). */ - QList< MessageItem * > currentThreadAsMessageItemList() const; + QList< MessageItem * > currentThreadAsMessageItemList() const; - /** + /** * Fast function that determines if the selection is empty */ - bool selectionEmpty() const; + bool selectionEmpty() const; - /** + /** * Selects the specified MessageItems. The current selection is NOT removed. * Use clearSelection() for that purpose. */ - void selectMessageItems( const QList< MessageItem * > &list ); + void selectMessageItems( const QList< MessageItem * > &list ); - /** + /** * Creates a persistent set for the specified MessageItems and * returns its reference. Later you can use this reference * to retrieve the list of MessageItems that are still valid. @@ -201,58 +201,58 @@ * while manipulating the view) so be sure to call deletePersistentSet() * when you no longer need it. */ - MessageItemSetReference createPersistentSet( const QList< MessageItem * > &items ); + MessageItemSetReference createPersistentSet( const QList< MessageItem * > &items ); - /** + /** * Returns the list of MessageItems that are still existing in the * set pointed by the specified reference. This list will contain * at most the messages that you have passed to createPersistentSet() * but may contain less (even 0) if these MessageItem object were removed * from the view for some reason. */ - QList< MessageItem * > persistentSetCurrentMessageItemList( MessageItemSetReference ref ); + QList< MessageItem * > persistentSetCurrentMessageItemList( MessageItemSetReference ref ); - /** + /** * Deletes the persistent set pointed by the specified reference. * If the set does not exist anymore, nothing happens. */ - void deletePersistentSet( MessageItemSetReference ref ); + void deletePersistentSet( MessageItemSetReference ref ); - /** + /** * If bMark is true this function marks the messages as "about to be removed" * so they appear dimmer and aren't selectable in the view. * If bMark is false then this function clears the "about to be removed" state * for the specified MessageItems. */ - void markMessageItemsAsAboutToBeRemoved( QList< MessageItem * > &items, bool bMark ); + void markMessageItemsAsAboutToBeRemoved( QList< MessageItem * > &items, bool bMark ); - /** + /** * Returns true if the current Aggregation is threaded, false otherwise * (or if there is no current Aggregation). */ - bool isThreaded() const; + bool isThreaded() const; - /** + /** * If expand is true then it expands the current thread, otherwise * collapses it. */ - void setCurrentThreadExpanded( bool expand ); + void setCurrentThreadExpanded( bool expand ); - /** + /** * If expand is true then it expands all the threads, otherwise * collapses them. */ - void setAllThreadsExpanded( bool expand ); + void setAllThreadsExpanded( bool expand ); - /** + /** * If expand is true then it expands all the groups (only the toplevel * group item: inner threads are NOT expanded). If expand is false * then it collapses all the groups. If no grouping is in effect * then this function does nothing. */ - void setAllGroupsExpanded( bool expand ); + void setAllGroupsExpanded( bool expand ); - /** + /** * Selects the next message item in the view. * * messageTypeFilter can be used to limit the selection to @@ -269,14 +269,14 @@ * \sa MessageList::Core::MessageTypeFilter * \sa MessageList::Core::ExistingSelectionBehaviour */ - bool selectNextMessageItem( - MessageTypeFilter messageTypeFilter, - ExistingSelectionBehaviour existingSelectionBehaviour, - bool centerItem, - bool loop - ); + bool selectNextMessageItem( + MessageTypeFilter messageTypeFilter, + ExistingSelectionBehaviour existingSelectionBehaviour, + bool centerItem, + bool loop + ); - /** + /** * Selects the previous message item in the view. * * messageTypeFilter can be used to limit the selection to @@ -293,14 +293,14 @@ * \sa MessageList::Core::MessageTypeFilter * \sa MessageList::Core::ExistingSelectionBehaviour */ - bool selectPreviousMessageItem( - MessageTypeFilter messageTypeFilter, - ExistingSelectionBehaviour existingSelectionBehaviour, - bool centerItem, - bool loop - ); + bool selectPreviousMessageItem( + MessageTypeFilter messageTypeFilter, + ExistingSelectionBehaviour existingSelectionBehaviour, + bool centerItem, + bool loop + ); - /** + /** * Focuses the next message item in the view without actually selecting it. * * messageTypeFilter can be used to limit the selection to @@ -311,9 +311,9 @@ * If loop is true then the "next" algorithm will restart from the beginning * of the list if the end is reached, otherwise it will just stop returning false. */ - bool focusNextMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); + bool focusNextMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); - /** + /** * Focuses the previous message item in the view without actually selecting it. * If unread is true then focuses the previous unread message item. * If centerItem is true then the specified item will be positioned @@ -321,168 +321,168 @@ * If loop is true then the "previous" algorithm will restart from the end * of the list if the beginning is reached, otherwise it will just stop returning false. */ - bool focusPreviousMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); + bool focusPreviousMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); - /** + /** * Selects the currently focused message item. If the currently focused * message is already selected (which is very likely) nothing happens. * If centerItem is true then the specified item will be positioned * at the center of the view, if possible. */ - void selectFocusedMessageItem( bool centerItem ); + void selectFocusedMessageItem( bool centerItem ); - /** + /** * Selects the first message item in the view that matches messageTypeFilter. * If centerItem is true then the specified item will be positioned * at the center of the view, if possible. */ - bool selectFirstMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem ); + bool selectFirstMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem ); - /** + /** * Selects the last message item in the view that matches messageTypeFilter. * If centerItem is true then the specified item will be positioned * at the center of the view, if possible. */ - bool selectLastMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem ); + bool selectLastMessageItem( MessageTypeFilter messageTypeFilter, bool centerItem ); - /** + /** * Sets the focus on the quick search line of the currently active tab. */ - void focusQuickSearch(); + void focusQuickSearch(); - /** + /** * Returns the Akonadi::MessageStatus in the current quicksearch field. */ - QList currentFilterStatus() const; + QList currentFilterStatus() const; - /** + /** * Returns the search term in the current quicksearch field. */ - QString currentFilterSearchString() const; + QString currentFilterSearchString() const; - /** + /** * Called to hide or show the specified row from the view. * @reimp */ - virtual void setRowHidden( int row, const QModelIndex & parent, bool hide ); + virtual void setRowHidden( int row, const QModelIndex & parent, bool hide ); - void sortOrderMenuAboutToShow(KMenu *menu); + void sortOrderMenuAboutToShow(KMenu *menu); - void aggregationMenuAboutToShow(KMenu *menu); + void aggregationMenuAboutToShow(KMenu *menu); - void themeMenuAboutToShow(KMenu *menu); + void themeMenuAboutToShow(KMenu *menu); - void setCollapseItem(const QModelIndex& index); - void setExpandItem(const QModelIndex& index); + void setCollapseItem(const QModelIndex& index); + void setExpandItem(const QModelIndex& index); - void setQuickSearchClickMessage(const QString &msg); + void setQuickSearchClickMessage(const QString &msg); protected: - /** + /** * Reimplemented in order to catch QHelpEvent */ - virtual bool event( QEvent *e ); + virtual bool event( QEvent *e ); - /** + /** * Reimplemented in order to catch palette, font and style changes */ - virtual void changeEvent( QEvent *e ); + virtual void changeEvent( QEvent *e ); - /** + /** * Reimplemented in order to apply theme column widths on the first show */ - virtual void showEvent( QShowEvent *e ); + virtual void showEvent( QShowEvent *e ); - /** + /** * Reimplemented in order to handle clicks with sub-item precision. */ - virtual void mousePressEvent( QMouseEvent * e ); + virtual void mousePressEvent( QMouseEvent * e ); - /** + /** * Reimplemented in order to handle double clicks with sub-item precision. */ - virtual void mouseDoubleClickEvent( QMouseEvent * e ); + virtual void mouseDoubleClickEvent( QMouseEvent * e ); - /** + /** * Reimplemented in order to handle DnD */ - virtual void mouseMoveEvent( QMouseEvent * e ); + virtual void mouseMoveEvent( QMouseEvent * e ); - /** + /** * Reimplemented in order to handle context menu request via keyboard */ - virtual void contextMenuEvent( QContextMenuEvent* e ); + virtual void contextMenuEvent( QContextMenuEvent* e ); - /** + /** * Reimplemented in order to handle message DnD */ - virtual void dragEnterEvent( QDragEnterEvent * e ); + virtual void dragEnterEvent( QDragEnterEvent * e ); - /** + /** * Reimplemented in order to handle message DnD */ - virtual void dragMoveEvent( QDragMoveEvent * e ); + virtual void dragMoveEvent( QDragMoveEvent * e ); - /** + /** * Reimplemented in order to handle message DnD */ - virtual void dropEvent( QDropEvent * e ); + virtual void dropEvent( QDropEvent * e ); - /** + /** * Reimplemented in order to resize columns when header is not visible */ - virtual void resizeEvent( QResizeEvent * e ); + virtual void resizeEvent( QResizeEvent * e ); - /** + /** * Reimplemented in order to kill the QTreeView column auto-resizing */ - virtual int sizeHintForColumn( int logicalColumnIndex ) const; + virtual int sizeHintForColumn( int logicalColumnIndex ) const; - /** + /** * Reimplemented in order to disable update of the geometries * while a job step is running (as it takes a very long time and it's called for every item insertion...) * TODO: not true anymore, it's called after a delay. */ - virtual void updateGeometries(); + virtual void updateGeometries(); - /** + /** * Returns true if the vertical scrollbar should keep to the top or bottom * while inserting items. */ - bool isScrollingLocked() const; + bool isScrollingLocked() const; - /** + /** * Used to enable/disable the ignoring of updateGeometries() calls. */ - void ignoreUpdateGeometries( bool ignore ); + void ignoreUpdateGeometries( bool ignore ); - /** + /** * This is called by the model from inside setFolder(). * It's called just after the model has been reset but before * any row has been inserted. This allows us to call updateThemeColumns() as needed. */ - void modelHasBeenReset(); + void modelHasBeenReset(); - void modelAboutToEmitLayoutChanged(); - void modelEmittedLayoutChanged(); + void modelAboutToEmitLayoutChanged(); + void modelEmittedLayoutChanged(); - /** + /** * Recursive helper for currentThreadAsMessageItemList() */ - void appendMessageItemChildren( MessageItem * par, QList< MessageItem * > &list ); + void appendMessageItemChildren( MessageItem * par, QList< MessageItem * > &list ); - /** + /** * This is called by the model to insulate us from certain QTreeView signals * This is because they may be spurious (caused by Model item rearrangements). */ - void ignoreCurrentChanges( bool ignore ); + void ignoreCurrentChanges( bool ignore ); - /** + /** * Expands or collapses the children of the specified item, recursively. */ - void setChildrenExpanded( const Item * parent, bool expand ); + void setChildrenExpanded( const Item * parent, bool expand ); - /** + /** * Finds the next message item with respect to the current item. * If there is no current item then the search starts from the beginning. * Returns 0 if no next message could be found. @@ -492,9 +492,9 @@ * If loop is true then restarts from the beginning if end is * reached, otherwise it just returns 0 in this case. */ - Item * nextMessageItem( MessageTypeFilter messageTypeFilter, bool loop ); + Item * nextMessageItem( MessageTypeFilter messageTypeFilter, bool loop ); - /** + /** * Finds message item that comes "after" the reference item. * If reference item is 0 then the search starts from the beginning. * Returns 0 if no next message could be found. @@ -504,9 +504,9 @@ * If loop is true then restarts from the beginning if end is * reached, otherwise it just returns 0 in this case. */ - Item * messageItemAfter( Item * referenceItem, MessageTypeFilter messageTypeFilter, bool loop ); + Item * messageItemAfter( Item * referenceItem, MessageTypeFilter messageTypeFilter, bool loop ); - /** + /** * Finds the first message item in the view. * * messageTypeFilter can be used to limit the selection to @@ -514,10 +514,10 @@ * * Returns 0 if the view is empty. */ - Item * firstMessageItem( MessageTypeFilter messageTypeFilter ) + Item * firstMessageItem( MessageTypeFilter messageTypeFilter ) { return messageItemAfter( 0, messageTypeFilter, false ); } - /** + /** * Finds the previous message item with respect to the current item. * If there is no current item then the search starts from the end. * Returns 0 if no previous message could be found. @@ -527,15 +527,15 @@ * If loop is true then restarts from the end if beginning is * reached, otherwise it just return 0 in this case. */ - Item * previousMessageItem( MessageTypeFilter messageTypeFilter, bool loop ); + Item * previousMessageItem( MessageTypeFilter messageTypeFilter, bool loop ); - /** + /** * Returns the deepest child that is visible (i.e. not in a collapsed tree) of * the specified reference item. */ - Item * deepestExpandedChild( Item * referenceItem ) const; + Item * deepestExpandedChild( Item * referenceItem ) const; - /** + /** * Finds message item that comes "before" the reference item. * If reference item is 0 then the search starts from the end. * Returns 0 if no next message could be found. @@ -545,9 +545,9 @@ * If loop is true then restarts from the beginning if end is * reached, otherwise it just returns 0 in this case. */ - Item * messageItemBefore( Item * referenceItem, MessageTypeFilter messageTypeFilter, bool loop ); + Item * messageItemBefore( Item * referenceItem, MessageTypeFilter messageTypeFilter, bool loop ); - /** + /** * Finds the last message item in the view. * * messageTypeFilter can be used to limit the selection to @@ -555,50 +555,50 @@ * * Returns 0 if the view is empty. */ - Item * lastMessageItem( MessageTypeFilter messageTypeFilter ) + Item * lastMessageItem( MessageTypeFilter messageTypeFilter ) { return messageItemBefore( 0, messageTypeFilter, false ); } - /** + /** * This is called by Model to signal a start of a lengthy job batch. * Note that this is NOT called for jobs that can be completed in a single step. */ - void modelJobBatchStarted(); + void modelJobBatchStarted(); - /** + /** * This is called by Model to signal the end of a lengthy job batch. * Note that this is NOT called for jobs that can be completed in a single step. */ - void modelJobBatchTerminated(); + void modelJobBatchTerminated(); - /** + /** * This is called by Model to signal that the initial loading stage of a newly * attached StorageModel is terminated. */ - void modelFinishedLoading(); + void modelFinishedLoading(); - /** + /** * Performs a change in the specified MessageItem status. * It first applies the change to the cached state in MessageItem and * then requests our parent widget to act on the storage. */ - void changeMessageStatus( MessageItem * it, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &unset ); - void changeMessageStatusRead( MessageItem *it, bool read ); + void changeMessageStatus( MessageItem * it, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &unset ); + void changeMessageStatusRead( MessageItem *it, bool read ); - /** + /** * Starts a short-delay timer connected to saveThemeColumnState(). * Used to accumulate consecutive changes and break out of the call stack * up to the main event loop (since in the call stack the column state might be left undefined). */ - void triggerDelayedSaveThemeColumnState(); + void triggerDelayedSaveThemeColumnState(); - /** + /** * Starts a short-delay timer connected to applyThemeColumns(). * Used to accumulate consecutive changes and break out of the call stack * up to the main event loop (since multiple resize events tend to be sent by Qt at startup). */ - void triggerDelayedApplyThemeColumns(); + void triggerDelayedApplyThemeColumns(); - /** + /** * This is used by the selection functions to grow/shrink the existing selection * according to the newly selected item passed as parameter. * If movingUp is true then: if the newly selected item is above the current selection top @@ -606,86 +606,86 @@ * newly selected item is below the current selection bottom then the selection is expanded * otherwise it's shrunk. */ - void growOrShrinkExistingSelection( const QModelIndex &newSelectedIndex, bool movingUp ); + void growOrShrinkExistingSelection( const QModelIndex &newSelectedIndex, bool movingUp ); public slots: - /** + /** * Collapses all the group headers (if present in the current Aggregation) */ - void slotCollapseAllGroups(); + void slotCollapseAllGroups(); - /** + /** * Expands all the group headers (if present in the current Aggregation) */ - void slotExpandAllGroups(); + void slotExpandAllGroups(); - /** + /** * Expands the currect item. * If it's a Message, it expands its thread, if its a group header it expands the group */ - void slotExpandCurrentItem(); + void slotExpandCurrentItem(); - /** + /** * Collapses the currect item. * If it's a Message, it collapses its thread, if its a group header it collapses the group */ - void slotCollapseCurrentItem(); + void slotCollapseCurrentItem(); protected slots: - /** + /** * Handles context menu requests for the header. */ - void slotHeaderContextMenuRequested( const QPoint &pnt ); + void slotHeaderContextMenuRequested( const QPoint &pnt ); - /** + /** * Handles the actions of the header context menu for showing/hiding a column. */ - void slotShowHideColumn( int columnIndex ); + void slotShowHideColumn( int columnIndex ); - /** + /** * Handles the Adjust Column Sizes action of the header context menu. */ - void slotAdjustColumnSizes(); + void slotAdjustColumnSizes(); - /** + /** * Handles the Show Default Columns action of the header context menu. */ - void slotShowDefaultColumns(); + void slotShowDefaultColumns(); - /** + /** * Handles the Display Tooltips action of the header context menu. */ - void slotDisplayTooltips( bool showTooltips ); + void slotDisplayTooltips( bool showTooltips ); - /** + /** * Handles section resizes in order to save the column widths */ - void slotHeaderSectionResized( int logicalIndex, int oldWidth, int newWidth ); + void slotHeaderSectionResized( int logicalIndex, int oldWidth, int newWidth ); - /** + /** * Handles selection item management */ - void slotSelectionChanged( const QItemSelection ¤t, const QItemSelection & ); + void slotSelectionChanged( const QItemSelection ¤t, const QItemSelection & ); - /** + /** * Saves the state of the columns (width and visility) to the currently selected theme object. */ - void saveThemeColumnState(); + void saveThemeColumnState(); - /** + /** * Applies the theme columns to this view. * Columns visible by default are shown, the other are hidden. * Visible columns are assigned space inside the view by using the size hints and some heuristics. */ - void applyThemeColumns(); + void applyThemeColumns(); private: - /// expand the whole thread (including all child messages) - Q_PRIVATE_SLOT(d, void expandFullThread( const QModelIndex& )) + /// expand the whole thread (including all child messages) + Q_PRIVATE_SLOT(d, void expandFullThread( const QModelIndex& )) - class Private; - Private * d; + class Private; + Private * d; }; // class View } // namespace Core diff -Nru kdepim-4.12.97/messagelist/core/widgetbase.cpp kdepim-4.13.0/messagelist/core/widgetbase.cpp --- kdepim-4.12.97/messagelist/core/widgetbase.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/widgetbase.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -62,858 +62,858 @@ class Widget::Private { public: - Private( Widget *owner ) - : q( owner ), - quickSearchLine( 0 ), - mView( 0 ), - mSearchTimer( 0 ), - mStorageModel( 0 ), mAggregation( 0 ), - mTheme( 0 ), mFilter( 0 ), - mStorageUsesPrivateTheme( false ), - mStorageUsesPrivateAggregation( false ), - mStorageUsesPrivateSortOrder( false ), - mStatusFilterComboPopulationInProgress( false ) - { } + Private( Widget *owner ) + : q( owner ), + quickSearchLine( 0 ), + mView( 0 ), + mSearchTimer( 0 ), + mStorageModel( 0 ), mAggregation( 0 ), + mTheme( 0 ), mFilter( 0 ), + mStorageUsesPrivateTheme( false ), + mStorageUsesPrivateAggregation( false ), + mStorageUsesPrivateSortOrder( false ), + mStatusFilterComboPopulationInProgress( false ) + { } - /** + /** * Small helper for switching SortOrder::MessageSorting and SortOrder::SortDirection * on the fly. * After doing this, the sort indicator in the header is updated. */ - void switchMessageSorting( SortOrder::MessageSorting messageSorting, - SortOrder::SortDirection sortDirection, - int logicalHeaderColumnIndex ); + void switchMessageSorting( SortOrder::MessageSorting messageSorting, + SortOrder::SortDirection sortDirection, + int logicalHeaderColumnIndex ); - /** + /** * Check if our sort order can still be used with this aggregation. * This can happen if the global aggregation changed, for example we can now * have "most recent in subtree" sorting with an aggregation without threading. * If this happens, reset to the default sort order and don't use the global sort * order. */ - void checkSortOrder( const StorageModel *storageModel ); + void checkSortOrder( const StorageModel *storageModel ); - void setDefaultAggregationForStorageModel( const StorageModel * storageModel ); - void setDefaultThemeForStorageModel( const StorageModel * storageModel ); - void setDefaultSortOrderForStorageModel( const StorageModel * storageModel ); - void applyFilter(); - - Widget * const q; - - QuickSearchLine *quickSearchLine; - View *mView; - QString mLastAggregationId; - QString mLastThemeId; - QTimer *mSearchTimer; - StorageModel * mStorageModel; ///< The currently displayed storage. The storage itself - /// is owned by MessageList::Widget. - Aggregation * mAggregation; ///< The currently set aggregation mode, a deep copy - Theme * mTheme; ///< The currently set theme, a deep copy - SortOrder mSortOrder; ///< The currently set sort order - Filter * mFilter; ///< The currently applied filter, owned by us. - bool mStorageUsesPrivateTheme; ///< true if the current folder does not use the global theme - bool mStorageUsesPrivateAggregation; ///< true if the current folder does not use the global aggregation - bool mStorageUsesPrivateSortOrder; ///< true if the current folder does not use the global sort order - KUrl mCurrentFolderUrl; ///< The Akonadi URL of the current folder - Akonadi::Collection mCurrentFolder; ///< The current folder - int mCurrentStatusFilterIndex; - bool mStatusFilterComboPopulationInProgress; + void setDefaultAggregationForStorageModel( const StorageModel * storageModel ); + void setDefaultThemeForStorageModel( const StorageModel * storageModel ); + void setDefaultSortOrderForStorageModel( const StorageModel * storageModel ); + void applyFilter(); + + Widget * const q; + + QuickSearchLine *quickSearchLine; + View *mView; + QString mLastAggregationId; + QString mLastThemeId; + QTimer *mSearchTimer; + StorageModel * mStorageModel; ///< The currently displayed storage. The storage itself + /// is owned by MessageList::Widget. + Aggregation * mAggregation; ///< The currently set aggregation mode, a deep copy + Theme * mTheme; ///< The currently set theme, a deep copy + SortOrder mSortOrder; ///< The currently set sort order + Filter * mFilter; ///< The currently applied filter, owned by us. + bool mStorageUsesPrivateTheme; ///< true if the current folder does not use the global theme + bool mStorageUsesPrivateAggregation; ///< true if the current folder does not use the global aggregation + bool mStorageUsesPrivateSortOrder; ///< true if the current folder does not use the global sort order + KUrl mCurrentFolderUrl; ///< The Akonadi URL of the current folder + Akonadi::Collection mCurrentFolder; ///< The current folder + int mCurrentStatusFilterIndex; + bool mStatusFilterComboPopulationInProgress; }; Widget::Widget( QWidget *pParent ) - : QWidget( pParent ), d( new Private( this ) ) + : QWidget( pParent ), d( new Private( this ) ) { - Manager::registerWidget( this ); - connect( Manager::instance(), SIGNAL(aggregationsChanged()), - this, SLOT(aggregationsChanged()) ); - connect( Manager::instance(), SIGNAL(themesChanged()), - this, SLOT(themesChanged()) ); - - setAutoFillBackground( true ); - setObjectName( QLatin1String( "messagelistwidget" ) ); - - QVBoxLayout * g = new QVBoxLayout( this ); - g->setMargin( 0 ); - g->setSpacing( 0 ); - - d->quickSearchLine = new QuickSearchLine; - connect(d->quickSearchLine, SIGNAL(clearButtonClicked()), SLOT(searchEditClearButtonClicked()) ); - - connect(d->quickSearchLine, SIGNAL(searchEditTextEdited(QString)), SLOT(searchEditTextEdited()) ); - connect(d->quickSearchLine, SIGNAL(searchOptionChanged()), SLOT(searchEditTextEdited()) ); - connect(d->quickSearchLine, SIGNAL(statusButtonsClicked()), SLOT(slotStatusButtonsClicked())); - g->addWidget( d->quickSearchLine, 0 ); - - d->mView = new View( this ); - d->mView->setFrameStyle( QFrame::NoFrame ); - d->mView->setSortOrder( &d->mSortOrder ); - d->mView->setObjectName( QLatin1String( "messagealistview" ) ); - g->addWidget( d->mView, 1 ); - - connect( d->mView->header(), SIGNAL(sectionClicked(int)), - SLOT(slotViewHeaderSectionClicked(int)) ); - d->mSearchTimer = 0; + Manager::registerWidget( this ); + connect( Manager::instance(), SIGNAL(aggregationsChanged()), + this, SLOT(aggregationsChanged()) ); + connect( Manager::instance(), SIGNAL(themesChanged()), + this, SLOT(themesChanged()) ); + + setAutoFillBackground( true ); + setObjectName( QLatin1String( "messagelistwidget" ) ); + + QVBoxLayout * g = new QVBoxLayout( this ); + g->setMargin( 0 ); + g->setSpacing( 0 ); + + d->quickSearchLine = new QuickSearchLine; + connect(d->quickSearchLine, SIGNAL(clearButtonClicked()), SLOT(searchEditClearButtonClicked()) ); + + connect(d->quickSearchLine, SIGNAL(searchEditTextEdited(QString)), SLOT(searchEditTextEdited()) ); + connect(d->quickSearchLine, SIGNAL(searchOptionChanged()), SLOT(searchEditTextEdited()) ); + connect(d->quickSearchLine, SIGNAL(statusButtonsClicked()), SLOT(slotStatusButtonsClicked())); + g->addWidget( d->quickSearchLine, 0 ); + + d->mView = new View( this ); + d->mView->setFrameStyle( QFrame::NoFrame ); + d->mView->setSortOrder( &d->mSortOrder ); + d->mView->setObjectName( QLatin1String( "messagealistview" ) ); + g->addWidget( d->mView, 1 ); + + connect( d->mView->header(), SIGNAL(sectionClicked(int)), + SLOT(slotViewHeaderSectionClicked(int)) ); + d->mSearchTimer = 0; } Widget::~Widget() { - d->mView->setStorageModel( 0 ); + d->mView->setStorageModel( 0 ); - Manager::unregisterWidget( this ); + Manager::unregisterWidget( this ); - delete d->mSearchTimer; - delete d->mTheme; - delete d->mAggregation; - delete d->mFilter; - delete d->mStorageModel; + delete d->mSearchTimer; + delete d->mTheme; + delete d->mAggregation; + delete d->mFilter; + delete d->mStorageModel; - delete d; + delete d; } void Widget::changeQuicksearchVisibility(bool show) { - KLineEdit * const lineEdit = d->quickSearchLine->searchEdit(); - QWidget * const comboBox = d->quickSearchLine->tagFilterComboBox(); - if ( !show ) { - //if we hide it we do not want to apply the filter, - //otherwise someone is maybe stuck with x new emails - //and cannot read it because of filter - lineEdit->clear(); - - //we focus the message list if we hide the searchbar - d->mView->setFocus( Qt::OtherFocusReason ); - } - else { - // on show: we focus the lineedit for fast filtering - lineEdit->setFocus( Qt::OtherFocusReason ); - if ( d->mFilter ) { - resetFilter(); - } - } - lineEdit->setVisible( show ); - comboBox->setVisible( show ); - d->quickSearchLine->lockSearch()->setVisible( show ); - Settings::self()->setShowQuickSearch( show ); + KLineEdit * const lineEdit = d->quickSearchLine->searchEdit(); + QWidget * const comboBox = d->quickSearchLine->tagFilterComboBox(); + if ( !show ) { + //if we hide it we do not want to apply the filter, + //otherwise someone is maybe stuck with x new emails + //and cannot read it because of filter + lineEdit->clear(); + + //we focus the message list if we hide the searchbar + d->mView->setFocus( Qt::OtherFocusReason ); + } + else { + // on show: we focus the lineedit for fast filtering + lineEdit->setFocus( Qt::OtherFocusReason ); + if ( d->mFilter ) { + resetFilter(); + } + } + lineEdit->setVisible( show ); + comboBox->setVisible( show ); + d->quickSearchLine->lockSearch()->setVisible( show ); + Settings::self()->setShowQuickSearch( show ); } void Widget::populateStatusFilterCombo() { - if (d->mStatusFilterComboPopulationInProgress) { - return; - } - d->mStatusFilterComboPopulationInProgress = true; - KComboBox *tagFilterComboBox = d->quickSearchLine->tagFilterComboBox(); - d->mCurrentStatusFilterIndex = (tagFilterComboBox->currentIndex() != -1) ? tagFilterComboBox->currentIndex() : 0; - disconnect( tagFilterComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(statusSelected(int)) ); + if (d->mStatusFilterComboPopulationInProgress) { + return; + } + d->mStatusFilterComboPopulationInProgress = true; + KComboBox *tagFilterComboBox = d->quickSearchLine->tagFilterComboBox(); + d->mCurrentStatusFilterIndex = (tagFilterComboBox->currentIndex() != -1) ? tagFilterComboBox->currentIndex() : 0; + disconnect( tagFilterComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(statusSelected(int)) ); - tagFilterComboBox->clear(); + tagFilterComboBox->clear(); - fillMessageTagCombo(); + fillMessageTagCombo(); } void Widget::addMessageTagItem(const QPixmap &icon, const QString &text, const QVariant &data) { - d->quickSearchLine->tagFilterComboBox()->addItem(icon, text, data); + d->quickSearchLine->tagFilterComboBox()->addItem(icon, text, data); } void Widget::setCurrentStatusFilterItem() { - d->quickSearchLine->updateComboboxVisibility(); - connect( d->quickSearchLine->tagFilterComboBox(), SIGNAL(currentIndexChanged(int)), - this, SLOT(statusSelected(int)) ); - d->quickSearchLine->tagFilterComboBox()->setCurrentIndex(d->mCurrentStatusFilterIndex>=d->quickSearchLine->tagFilterComboBox()->count() ? 0 : d->mCurrentStatusFilterIndex ); - d->mStatusFilterComboPopulationInProgress = false; + d->quickSearchLine->updateComboboxVisibility(); + connect( d->quickSearchLine->tagFilterComboBox(), SIGNAL(currentIndexChanged(int)), + this, SLOT(statusSelected(int)) ); + d->quickSearchLine->tagFilterComboBox()->setCurrentIndex(d->mCurrentStatusFilterIndex>=d->quickSearchLine->tagFilterComboBox()->count() ? 0 : d->mCurrentStatusFilterIndex ); + d->mStatusFilterComboPopulationInProgress = false; } MessageItem *Widget::currentMessageItem() const { - return view()->currentMessageItem(); + return view()->currentMessageItem(); } QList Widget::currentFilterStatus() const { - if ( d->mFilter ) - return d->mFilter->status(); - return QList(); + if ( d->mFilter ) + return d->mFilter->status(); + return QList(); } QString Widget::currentFilterSearchString() const { - if ( d->mFilter ) - return d->mFilter->searchString(); - return QString(); + if ( d->mFilter ) + return d->mFilter->searchString(); + return QString(); } QString Widget::currentFilterTagId() const { - if ( d->mFilter ) - return d->mFilter->tagId(); + if ( d->mFilter ) + return d->mFilter->tagId(); - return QString(); + return QString(); } void Widget::Private::setDefaultAggregationForStorageModel( const StorageModel * storageModel ) { - const Aggregation * opt = Manager::instance()->aggregationForStorageModel( storageModel, &mStorageUsesPrivateAggregation ); + const Aggregation * opt = Manager::instance()->aggregationForStorageModel( storageModel, &mStorageUsesPrivateAggregation ); - Q_ASSERT( opt ); + Q_ASSERT( opt ); - delete mAggregation; - mAggregation = new Aggregation( *opt ); + delete mAggregation; + mAggregation = new Aggregation( *opt ); - mView->setAggregation( mAggregation ); + mView->setAggregation( mAggregation ); - mLastAggregationId = opt->id(); + mLastAggregationId = opt->id(); } void Widget::Private::setDefaultThemeForStorageModel( const StorageModel * storageModel ) { - const Theme * opt = Manager::instance()->themeForStorageModel( storageModel, &mStorageUsesPrivateTheme ); + const Theme * opt = Manager::instance()->themeForStorageModel( storageModel, &mStorageUsesPrivateTheme ); - Q_ASSERT( opt ); + Q_ASSERT( opt ); - delete mTheme; - mTheme = new Theme( *opt ); + delete mTheme; + mTheme = new Theme( *opt ); - mView->setTheme( mTheme ); + mView->setTheme( mTheme ); - mLastThemeId = opt->id(); + mLastThemeId = opt->id(); } void Widget::Private::checkSortOrder( const StorageModel *storageModel ) { - if ( storageModel && mAggregation && !mSortOrder.validForAggregation( mAggregation ) ) { - kDebug() << "Could not restore sort order for folder" << storageModel->id(); - mSortOrder = SortOrder::defaultForAggregation( mAggregation, mSortOrder ); - - // Change the global sort order if the sort order didn't fit the global aggregation. - // Otherwise, if it is a per-folder aggregation, make the sort order per-folder too. - if ( mStorageUsesPrivateAggregation ) - mStorageUsesPrivateSortOrder = true; - if ( mStorageModel ) { - Manager::instance()->saveSortOrderForStorageModel( storageModel, mSortOrder, - mStorageUsesPrivateSortOrder ); + if ( storageModel && mAggregation && !mSortOrder.validForAggregation( mAggregation ) ) { + kDebug() << "Could not restore sort order for folder" << storageModel->id(); + mSortOrder = SortOrder::defaultForAggregation( mAggregation, mSortOrder ); + + // Change the global sort order if the sort order didn't fit the global aggregation. + // Otherwise, if it is a per-folder aggregation, make the sort order per-folder too. + if ( mStorageUsesPrivateAggregation ) + mStorageUsesPrivateSortOrder = true; + if ( mStorageModel ) { + Manager::instance()->saveSortOrderForStorageModel( storageModel, mSortOrder, + mStorageUsesPrivateSortOrder ); + } + switchMessageSorting( mSortOrder.messageSorting(), mSortOrder.messageSortDirection(), -1 ); } - switchMessageSorting( mSortOrder.messageSorting(), mSortOrder.messageSortDirection(), -1 ); - } } void Widget::Private::setDefaultSortOrderForStorageModel( const StorageModel * storageModel ) { - // Load the sort order from config and update column headers - mSortOrder = Manager::instance()->sortOrderForStorageModel( storageModel, &mStorageUsesPrivateSortOrder ); - switchMessageSorting( mSortOrder.messageSorting(), mSortOrder.messageSortDirection(), -1 ); - checkSortOrder( storageModel ); + // Load the sort order from config and update column headers + mSortOrder = Manager::instance()->sortOrderForStorageModel( storageModel, &mStorageUsesPrivateSortOrder ); + switchMessageSorting( mSortOrder.messageSorting(), mSortOrder.messageSortDirection(), -1 ); + checkSortOrder( storageModel ); } void Widget::saveCurrentSelection() { - if ( d->mStorageModel ) - { - // Save the current selection - MessageItem * lastSelectedMessageItem = d->mView->currentMessageItem( false ); - if ( lastSelectedMessageItem ) { - d->mStorageModel->savePreSelectedMessage( - lastSelectedMessageItem ? lastSelectedMessageItem->uniqueId() : 0 - ); + if ( d->mStorageModel ) + { + // Save the current selection + MessageItem * lastSelectedMessageItem = d->mView->currentMessageItem( false ); + if ( lastSelectedMessageItem ) { + d->mStorageModel->savePreSelectedMessage( + lastSelectedMessageItem ? lastSelectedMessageItem->uniqueId() : 0 + ); + } } - } } void Widget::setStorageModel( StorageModel * storageModel, PreSelectionMode preSelectionMode ) { - if ( storageModel == d->mStorageModel ) - return; // nuthin to do here + if ( storageModel == d->mStorageModel ) + return; // nuthin to do here + + d->setDefaultAggregationForStorageModel( storageModel ); + d->setDefaultThemeForStorageModel( storageModel ); + d->setDefaultSortOrderForStorageModel( storageModel ); + + if(!d->quickSearchLine->lockSearch()->isChecked()) { + if ( d->mSearchTimer ) { + d->mSearchTimer->stop(); + delete d->mSearchTimer; + d->mSearchTimer = 0; + } + + d->quickSearchLine->searchEdit()->clear(); + + if ( d->mFilter ) { + resetFilter(); + } + } + StorageModel * oldModel = d->mStorageModel; + + d->mStorageModel = storageModel; + d->mView->setStorageModel( d->mStorageModel, preSelectionMode ); + + delete oldModel; - d->setDefaultAggregationForStorageModel( storageModel ); - d->setDefaultThemeForStorageModel( storageModel ); - d->setDefaultSortOrderForStorageModel( storageModel ); - - if(!d->quickSearchLine->lockSearch()->isChecked()) { - if ( d->mSearchTimer ) { - d->mSearchTimer->stop(); - delete d->mSearchTimer; - d->mSearchTimer = 0; - } - - d->quickSearchLine->searchEdit()->clear(); - - if ( d->mFilter ) { - resetFilter(); - } - } - StorageModel * oldModel = d->mStorageModel; - - d->mStorageModel = storageModel; - d->mView->setStorageModel( d->mStorageModel, preSelectionMode ); - - delete oldModel; - - d->quickSearchLine->tagFilterComboBox()->setEnabled( d->mStorageModel ); - d->quickSearchLine->searchEdit()->setEnabled( d->mStorageModel ); - d->quickSearchLine->setContainsOutboundMessages( d->mStorageModel->containsOutboundMessages() ); + d->quickSearchLine->tagFilterComboBox()->setEnabled( d->mStorageModel ); + d->quickSearchLine->searchEdit()->setEnabled( d->mStorageModel ); + d->quickSearchLine->setContainsOutboundMessages( d->mStorageModel->containsOutboundMessages() ); } StorageModel *Widget::storageModel() const { - return d->mStorageModel; + return d->mStorageModel; } KLineEdit *Widget::quickSearch() const { - return d->quickSearchLine->searchEdit(); + return d->quickSearchLine->searchEdit(); } View *Widget::view() const { - return d->mView; + return d->mView; } void Widget::themeMenuAboutToShow() { - if ( !d->mStorageModel ) - return; + if ( !d->mStorageModel ) + return; - KMenu * menu = dynamic_cast< KMenu * >( sender() ); - if ( !menu ) - return; - themeMenuAboutToShow(menu); + KMenu * menu = dynamic_cast< KMenu * >( sender() ); + if ( !menu ) + return; + themeMenuAboutToShow(menu); } void Widget::themeMenuAboutToShow(KMenu *menu) { - menu->clear(); + menu->clear(); - menu->addTitle( i18n( "Theme" ) ); + menu->addTitle( i18n( "Theme" ) ); - QActionGroup * grp = new QActionGroup( menu ); + QActionGroup * grp = new QActionGroup( menu ); - QList< Theme * > sortedThemes = Manager::instance()->themes().values(); + QList< Theme * > sortedThemes = Manager::instance()->themes().values(); - QAction * act; + QAction * act; - qSort(sortedThemes.begin(),sortedThemes.end(),MessageList::Core::Theme::compareName); + qSort(sortedThemes.begin(),sortedThemes.end(),MessageList::Core::Theme::compareName); - QList< Theme * >::ConstIterator endTheme( sortedThemes.constEnd() ); - for ( QList< Theme * >::ConstIterator it = sortedThemes.constBegin(); it != endTheme; ++it ) - { - act = menu->addAction( ( *it )->name() ); - act->setCheckable( true ); - grp->addAction( act ); - act->setChecked( d->mLastThemeId == ( *it )->id() ); - act->setData( QVariant( ( *it )->id() ) ); - connect( act, SIGNAL(triggered(bool)), - SLOT(themeSelected(bool)) ); - } + QList< Theme * >::ConstIterator endTheme( sortedThemes.constEnd() ); + for ( QList< Theme * >::ConstIterator it = sortedThemes.constBegin(); it != endTheme; ++it ) + { + act = menu->addAction( ( *it )->name() ); + act->setCheckable( true ); + grp->addAction( act ); + act->setChecked( d->mLastThemeId == ( *it )->id() ); + act->setData( QVariant( ( *it )->id() ) ); + connect( act, SIGNAL(triggered(bool)), + SLOT(themeSelected(bool)) ); + } - menu->addSeparator(); + menu->addSeparator(); - act = menu->addAction( i18n( "Configure..." ) ); - connect( act, SIGNAL(triggered(bool)), - SLOT(configureThemes()) ); + act = menu->addAction( i18n( "Configure..." ) ); + connect( act, SIGNAL(triggered(bool)), + SLOT(configureThemes()) ); } void Widget::setPrivateSortOrderForStorage() { - if ( !d->mStorageModel ) - return; + if ( !d->mStorageModel ) + return; - d->mStorageUsesPrivateSortOrder = !d->mStorageUsesPrivateSortOrder; + d->mStorageUsesPrivateSortOrder = !d->mStorageUsesPrivateSortOrder; - Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, - d->mStorageUsesPrivateSortOrder ); + Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, + d->mStorageUsesPrivateSortOrder ); } void Widget::configureThemes() { - Utils::ConfigureThemesDialog *dialog = new Utils::ConfigureThemesDialog( window() ); - dialog->selectTheme( d->mLastThemeId ); - dialog->show(); + Utils::ConfigureThemesDialog *dialog = new Utils::ConfigureThemesDialog( window() ); + dialog->selectTheme( d->mLastThemeId ); + dialog->show(); } void Widget::themeSelected( bool ) { - if ( !d->mStorageModel ) - return; // nuthin to do + if ( !d->mStorageModel ) + return; // nuthin to do - QAction * act = dynamic_cast< QAction * >( sender() ); - if ( !act ) - return; + QAction * act = dynamic_cast< QAction * >( sender() ); + if ( !act ) + return; - QVariant v = act->data(); - const QString id = v.toString(); + QVariant v = act->data(); + const QString id = v.toString(); - if ( id.isEmpty() ) - return; + if ( id.isEmpty() ) + return; - const Theme * opt = Manager::instance()->theme( id ); + const Theme * opt = Manager::instance()->theme( id ); - delete d->mTheme; - d->mTheme = new Theme( *opt ); + delete d->mTheme; + d->mTheme = new Theme( *opt ); - d->mView->setTheme( d->mTheme ); + d->mView->setTheme( d->mTheme ); - d->mLastThemeId = opt->id(); + d->mLastThemeId = opt->id(); - //mStorageUsesPrivateTheme = false; + //mStorageUsesPrivateTheme = false; - Manager::instance()->saveThemeForStorageModel( d->mStorageModel, opt->id(), d->mStorageUsesPrivateTheme ); + Manager::instance()->saveThemeForStorageModel( d->mStorageModel, opt->id(), d->mStorageUsesPrivateTheme ); - d->mView->reload(); + d->mView->reload(); } void Widget::aggregationMenuAboutToShow() { - KMenu * menu = dynamic_cast< KMenu * >( sender() ); - if ( !menu ) - return; - aggregationMenuAboutToShow(menu); + KMenu * menu = dynamic_cast< KMenu * >( sender() ); + if ( !menu ) + return; + aggregationMenuAboutToShow(menu); } void Widget::aggregationMenuAboutToShow(KMenu *menu) { - menu->clear(); + menu->clear(); - menu->addTitle( i18n( "Aggregation" ) ); + menu->addTitle( i18n( "Aggregation" ) ); - QActionGroup * grp = new QActionGroup( menu ); + QActionGroup * grp = new QActionGroup( menu ); - QList< Aggregation * > sortedAggregations = Manager::instance()->aggregations().values(); + QList< Aggregation * > sortedAggregations = Manager::instance()->aggregations().values(); - QAction * act; + QAction * act; - qSort(sortedAggregations.begin(),sortedAggregations.end(), MessageList::Core::Aggregation::compareName); + qSort(sortedAggregations.begin(),sortedAggregations.end(), MessageList::Core::Aggregation::compareName); - QList::ConstIterator endagg( sortedAggregations.constEnd() ); + QList::ConstIterator endagg( sortedAggregations.constEnd() ); - for ( QList< Aggregation * >::ConstIterator it = sortedAggregations.constBegin(); it != endagg; ++it ) { - act = menu->addAction( ( *it )->name() ); - act->setCheckable( true ); - grp->addAction( act ); - act->setChecked( d->mLastAggregationId == ( *it )->id() ); - act->setData( QVariant( ( *it )->id() ) ); - connect( act, SIGNAL(triggered(bool)), - SLOT(aggregationSelected(bool)) ); - } + for ( QList< Aggregation * >::ConstIterator it = sortedAggregations.constBegin(); it != endagg; ++it ) { + act = menu->addAction( ( *it )->name() ); + act->setCheckable( true ); + grp->addAction( act ); + act->setChecked( d->mLastAggregationId == ( *it )->id() ); + act->setData( QVariant( ( *it )->id() ) ); + connect( act, SIGNAL(triggered(bool)), + SLOT(aggregationSelected(bool)) ); + } - menu->addSeparator(); + menu->addSeparator(); - act = menu->addAction( i18n( "Configure..." ) ); - act->setData( QVariant( QString() ) ); - connect( act, SIGNAL(triggered(bool)), - SLOT(aggregationSelected(bool)) ); + act = menu->addAction( i18n( "Configure..." ) ); + act->setData( QVariant( QString() ) ); + connect( act, SIGNAL(triggered(bool)), + SLOT(aggregationSelected(bool)) ); } void Widget::aggregationSelected( bool ) { - QAction * act = dynamic_cast< QAction * >( sender() ); - if ( !act ) - return; - - QVariant v = act->data(); - QString id = v.toString(); - - if ( id.isEmpty() ) { - Utils::ConfigureAggregationsDialog *dialog = new Utils::ConfigureAggregationsDialog( window() ); - dialog->selectAggregation( d->mLastAggregationId ); - dialog->show(); - return; - } + QAction * act = dynamic_cast< QAction * >( sender() ); + if ( !act ) + return; - if ( !d->mStorageModel ) - return; // nuthin to do + QVariant v = act->data(); + QString id = v.toString(); - const Aggregation * opt = Manager::instance()->aggregation( id ); + if ( id.isEmpty() ) { + Utils::ConfigureAggregationsDialog *dialog = new Utils::ConfigureAggregationsDialog( window() ); + dialog->selectAggregation( d->mLastAggregationId ); + dialog->show(); + return; + } + + if ( !d->mStorageModel ) + return; // nuthin to do + + const Aggregation * opt = Manager::instance()->aggregation( id ); - delete d->mAggregation; - d->mAggregation = new Aggregation( *opt ); + delete d->mAggregation; + d->mAggregation = new Aggregation( *opt ); - d->mView->setAggregation( d->mAggregation ); + d->mView->setAggregation( d->mAggregation ); - d->mLastAggregationId = opt->id(); + d->mLastAggregationId = opt->id(); - //mStorageUsesPrivateAggregation = false; + //mStorageUsesPrivateAggregation = false; - Manager::instance()->saveAggregationForStorageModel( d->mStorageModel, opt->id(), d->mStorageUsesPrivateAggregation ); + Manager::instance()->saveAggregationForStorageModel( d->mStorageModel, opt->id(), d->mStorageUsesPrivateAggregation ); - // The sort order might not be valid anymore for this aggregation - d->checkSortOrder( d->mStorageModel ); + // The sort order might not be valid anymore for this aggregation + d->checkSortOrder( d->mStorageModel ); - d->mView->reload(); + d->mView->reload(); } void Widget::sortOrderMenuAboutToShow() { - if ( !d->mAggregation ) - return; + if ( !d->mAggregation ) + return; - KMenu * menu = dynamic_cast< KMenu * >( sender() ); - if ( !menu ) - return; - sortOrderMenuAboutToShow(menu); + KMenu * menu = dynamic_cast< KMenu * >( sender() ); + if ( !menu ) + return; + sortOrderMenuAboutToShow(menu); } void Widget::sortOrderMenuAboutToShow(KMenu *menu) { - menu->clear(); - - menu->addTitle( i18n( "Message Sort Order" ) ); - - QActionGroup * grp; - QAction * act; - QList< QPair< QString, int > > options; - QList< QPair< QString, int > >::ConstIterator it; + menu->clear(); - grp = new QActionGroup( menu ); + menu->addTitle( i18n( "Message Sort Order" ) ); - options = SortOrder::enumerateMessageSortingOptions( d->mAggregation->threading() ); - QList< QPair< QString, int > >::ConstIterator end( options.constEnd() ); - for ( it = options.constBegin(); it != end; ++it ) { - act = menu->addAction( ( *it ).first ); - act->setCheckable( true ); - grp->addAction( act ); - act->setChecked( d->mSortOrder.messageSorting() == ( *it ).second ); - act->setData( QVariant( ( *it ).second ) ); - } - - connect( grp, SIGNAL(triggered(QAction*)), - SLOT(messageSortingSelected(QAction*)) ); - - options = SortOrder::enumerateMessageSortDirectionOptions( d->mSortOrder.messageSorting() ); - - if ( options.size() >= 2 ) { - menu->addTitle( i18n( "Message Sort Direction" ) ); + QActionGroup * grp; + QAction * act; + QList< QPair< QString, int > > options; + QList< QPair< QString, int > >::ConstIterator it; grp = new QActionGroup( menu ); - end = options.constEnd(); + + options = SortOrder::enumerateMessageSortingOptions( d->mAggregation->threading() ); + QList< QPair< QString, int > >::ConstIterator end( options.constEnd() ); for ( it = options.constBegin(); it != end; ++it ) { - act = menu->addAction( ( *it ).first ); - act->setCheckable( true ); - grp->addAction( act ); - act->setChecked( d->mSortOrder.messageSortDirection() == ( *it ).second ); - act->setData( QVariant( ( *it ).second ) ); + act = menu->addAction( ( *it ).first ); + act->setCheckable( true ); + grp->addAction( act ); + act->setChecked( d->mSortOrder.messageSorting() == ( *it ).second ); + act->setData( QVariant( ( *it ).second ) ); } connect( grp, SIGNAL(triggered(QAction*)), - SLOT(messageSortDirectionSelected(QAction*)) ); - } + SLOT(messageSortingSelected(QAction*)) ); - options = SortOrder::enumerateGroupSortingOptions( d->mAggregation->grouping() ); + options = SortOrder::enumerateMessageSortDirectionOptions( d->mSortOrder.messageSorting() ); - if ( options.size() >= 2 ) { - menu->addTitle( i18n( "Group Sort Order" ) ); + if ( options.size() >= 2 ) { + menu->addTitle( i18n( "Message Sort Direction" ) ); - grp = new QActionGroup( menu ); + grp = new QActionGroup( menu ); + end = options.constEnd(); + for ( it = options.constBegin(); it != end; ++it ) { + act = menu->addAction( ( *it ).first ); + act->setCheckable( true ); + grp->addAction( act ); + act->setChecked( d->mSortOrder.messageSortDirection() == ( *it ).second ); + act->setData( QVariant( ( *it ).second ) ); + } - end = options.constEnd(); - for ( it = options.constBegin(); it != end; ++it ) { - act = menu->addAction( ( *it ).first ); - act->setCheckable( true ); - grp->addAction( act ); - act->setChecked( d->mSortOrder.groupSorting() == ( *it ).second ); - act->setData( QVariant( ( *it ).second ) ); + connect( grp, SIGNAL(triggered(QAction*)), + SLOT(messageSortDirectionSelected(QAction*)) ); } - connect( grp, SIGNAL(triggered(QAction*)), - SLOT(groupSortingSelected(QAction*)) ); - } + options = SortOrder::enumerateGroupSortingOptions( d->mAggregation->grouping() ); - options = SortOrder::enumerateGroupSortDirectionOptions( d->mAggregation->grouping(), - d->mSortOrder.groupSorting() ); + if ( options.size() >= 2 ) { + menu->addTitle( i18n( "Group Sort Order" ) ); - if ( options.size() >= 2 ) { - menu->addTitle( i18n( "Group Sort Direction" ) ); + grp = new QActionGroup( menu ); - grp = new QActionGroup( menu ); - end = options.constEnd(); - for ( it = options.constBegin(); it != end; ++it ) { - act = menu->addAction( ( *it ).first ); - act->setCheckable( true ); - grp->addAction( act ); - act->setChecked( d->mSortOrder.groupSortDirection() == ( *it ).second ); - act->setData( QVariant( ( *it ).second ) ); + end = options.constEnd(); + for ( it = options.constBegin(); it != end; ++it ) { + act = menu->addAction( ( *it ).first ); + act->setCheckable( true ); + grp->addAction( act ); + act->setChecked( d->mSortOrder.groupSorting() == ( *it ).second ); + act->setData( QVariant( ( *it ).second ) ); + } + + connect( grp, SIGNAL(triggered(QAction*)), + SLOT(groupSortingSelected(QAction*)) ); } - connect( grp, SIGNAL(triggered(QAction*)), - SLOT(groupSortDirectionSelected(QAction*)) ); - } + options = SortOrder::enumerateGroupSortDirectionOptions( d->mAggregation->grouping(), + d->mSortOrder.groupSorting() ); + + if ( options.size() >= 2 ) { + menu->addTitle( i18n( "Group Sort Direction" ) ); + + grp = new QActionGroup( menu ); + end = options.constEnd(); + for ( it = options.constBegin(); it != end; ++it ) { + act = menu->addAction( ( *it ).first ); + act->setCheckable( true ); + grp->addAction( act ); + act->setChecked( d->mSortOrder.groupSortDirection() == ( *it ).second ); + act->setData( QVariant( ( *it ).second ) ); + } - menu->addSeparator(); - act = menu->addAction( i18n( "Folder Always Uses This Sort Order" ) ); - act->setCheckable( true ); - act->setChecked( d->mStorageUsesPrivateSortOrder ); - connect( act, SIGNAL(triggered(bool)), - SLOT(setPrivateSortOrderForStorage()) ); + connect( grp, SIGNAL(triggered(QAction*)), + SLOT(groupSortDirectionSelected(QAction*)) ); + } + + menu->addSeparator(); + act = menu->addAction( i18n( "Folder Always Uses This Sort Order" ) ); + act->setCheckable( true ); + act->setChecked( d->mStorageUsesPrivateSortOrder ); + connect( act, SIGNAL(triggered(bool)), + SLOT(setPrivateSortOrderForStorage()) ); } void Widget::Private::switchMessageSorting( SortOrder::MessageSorting messageSorting, SortOrder::SortDirection sortDirection, int logicalHeaderColumnIndex ) { - mSortOrder.setMessageSorting( messageSorting ); - mSortOrder.setMessageSortDirection( sortDirection ); + mSortOrder.setMessageSorting( messageSorting ); + mSortOrder.setMessageSortDirection( sortDirection ); - // If the logicalHeaderColumnIndex was specified then we already know which - // column we should set the sort indicator to. If it wasn't specified (it's -1) - // then we need to find it out in the theme. - - if ( logicalHeaderColumnIndex == -1 ) - { - // try to find the specified message sorting in the theme columns - const QList< Theme::Column * > & columns = mTheme->columns(); - int idx = 0; + // If the logicalHeaderColumnIndex was specified then we already know which + // column we should set the sort indicator to. If it wasn't specified (it's -1) + // then we need to find it out in the theme. - // First try with a well defined message sorting. - - foreach( const Theme::Column* column, columns ) + if ( logicalHeaderColumnIndex == -1 ) { - if ( !mView->header()->isSectionHidden( idx ) ) - { - if ( column->messageSorting() == messageSorting ) + // try to find the specified message sorting in the theme columns + const QList< Theme::Column * > & columns = mTheme->columns(); + int idx = 0; + + // First try with a well defined message sorting. + + foreach( const Theme::Column* column, columns ) { - // found a visible column with this message sorting - logicalHeaderColumnIndex = idx; - break; + if ( !mView->header()->isSectionHidden( idx ) ) + { + if ( column->messageSorting() == messageSorting ) + { + // found a visible column with this message sorting + logicalHeaderColumnIndex = idx; + break; + } + } + ++idx; + } + + // if still not found, try again with a wider range + if ( logicalHeaderColumnIndex == -1 ) + { + idx = 0; + foreach( const Theme::Column* column, columns ) + { + if ( !mView->header()->isSectionHidden( idx ) ) + { + if ( + ( + ( column->messageSorting() == SortOrder::SortMessagesBySenderOrReceiver ) || + ( column->messageSorting() == SortOrder::SortMessagesByReceiver ) || + ( column->messageSorting() == SortOrder::SortMessagesBySender ) + ) && + ( + ( messageSorting == SortOrder::SortMessagesBySenderOrReceiver ) || + ( messageSorting == SortOrder::SortMessagesByReceiver ) || + ( messageSorting == SortOrder::SortMessagesBySender ) + ) + ) + { + // found a visible column with this message sorting + logicalHeaderColumnIndex = idx; + break; + } + } + ++idx; + } } - } - ++idx; } - // if still not found, try again with a wider range if ( logicalHeaderColumnIndex == -1 ) { - idx = 0; - foreach( const Theme::Column* column, columns ) - { - if ( !mView->header()->isSectionHidden( idx ) ) - { - if ( - ( - ( column->messageSorting() == SortOrder::SortMessagesBySenderOrReceiver ) || - ( column->messageSorting() == SortOrder::SortMessagesByReceiver ) || - ( column->messageSorting() == SortOrder::SortMessagesBySender ) - ) && - ( - ( messageSorting == SortOrder::SortMessagesBySenderOrReceiver ) || - ( messageSorting == SortOrder::SortMessagesByReceiver ) || - ( messageSorting == SortOrder::SortMessagesBySender ) - ) - ) - { - // found a visible column with this message sorting - logicalHeaderColumnIndex = idx; - break; - } - } - ++idx; - } - } - } - - if ( logicalHeaderColumnIndex == -1 ) - { - // not found: either not a column-based sorting or the related column is hidden - mView->header()->setSortIndicatorShown( false ); - return; - } - - mView->header()->setSortIndicatorShown( true ); - - if ( sortDirection == SortOrder::Ascending ) - mView->header()->setSortIndicator( logicalHeaderColumnIndex, Qt::AscendingOrder ); - else - mView->header()->setSortIndicator( logicalHeaderColumnIndex, Qt::DescendingOrder ); + // not found: either not a column-based sorting or the related column is hidden + mView->header()->setSortIndicatorShown( false ); + return; + } + + mView->header()->setSortIndicatorShown( true ); + + if ( sortDirection == SortOrder::Ascending ) + mView->header()->setSortIndicator( logicalHeaderColumnIndex, Qt::AscendingOrder ); + else + mView->header()->setSortIndicator( logicalHeaderColumnIndex, Qt::DescendingOrder ); } void Widget::messageSortingSelected( QAction *action ) { - if ( !d->mAggregation ) - return; - if ( !action ) - return; + if ( !d->mAggregation ) + return; + if ( !action ) + return; - if ( !d->mStorageModel ) - return; + if ( !d->mStorageModel ) + return; - bool ok; - SortOrder::MessageSorting ord = static_cast< SortOrder::MessageSorting >( action->data().toInt( &ok ) ); + bool ok; + SortOrder::MessageSorting ord = static_cast< SortOrder::MessageSorting >( action->data().toInt( &ok ) ); - if ( !ok ) - return; + if ( !ok ) + return; - d->switchMessageSorting( ord, d->mSortOrder.messageSortDirection(), -1 ); - Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, - d->mStorageUsesPrivateSortOrder ); + d->switchMessageSorting( ord, d->mSortOrder.messageSortDirection(), -1 ); + Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, + d->mStorageUsesPrivateSortOrder ); - d->mView->reload(); + d->mView->reload(); } void Widget::messageSortDirectionSelected( QAction *action ) { - if ( !d->mAggregation ) - return; - if ( !action ) - return; - if ( !d->mStorageModel ) - return; + if ( !d->mAggregation ) + return; + if ( !action ) + return; + if ( !d->mStorageModel ) + return; - bool ok; - SortOrder::SortDirection ord = static_cast< SortOrder::SortDirection >( action->data().toInt( &ok ) ); + bool ok; + SortOrder::SortDirection ord = static_cast< SortOrder::SortDirection >( action->data().toInt( &ok ) ); - if ( !ok ) - return; + if ( !ok ) + return; - d->switchMessageSorting( d->mSortOrder.messageSorting(), ord, -1 ); - Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, - d->mStorageUsesPrivateSortOrder ); + d->switchMessageSorting( d->mSortOrder.messageSorting(), ord, -1 ); + Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, + d->mStorageUsesPrivateSortOrder ); - d->mView->reload(); + d->mView->reload(); } void Widget::groupSortingSelected( QAction *action ) { - if ( !d->mAggregation ) - return; - if ( !action ) - return; + if ( !d->mAggregation ) + return; + if ( !action ) + return; - if ( !d->mStorageModel ) - return; + if ( !d->mStorageModel ) + return; - bool ok; - SortOrder::GroupSorting ord = static_cast< SortOrder::GroupSorting >( action->data().toInt( &ok ) ); + bool ok; + SortOrder::GroupSorting ord = static_cast< SortOrder::GroupSorting >( action->data().toInt( &ok ) ); - if ( !ok ) - return; + if ( !ok ) + return; - d->mSortOrder.setGroupSorting( ord ); - Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, - d->mStorageUsesPrivateSortOrder ); + d->mSortOrder.setGroupSorting( ord ); + Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, + d->mStorageUsesPrivateSortOrder ); - d->mView->reload(); + d->mView->reload(); } void Widget::groupSortDirectionSelected( QAction *action ) { - if ( !d->mAggregation ) - return; - if ( !action ) - return; - if ( !d->mStorageModel ) - return; + if ( !d->mAggregation ) + return; + if ( !action ) + return; + if ( !d->mStorageModel ) + return; - bool ok; - SortOrder::SortDirection ord = static_cast< SortOrder::SortDirection >( action->data().toInt( &ok ) ); + bool ok; + SortOrder::SortDirection ord = static_cast< SortOrder::SortDirection >( action->data().toInt( &ok ) ); - if ( !ok ) - return; + if ( !ok ) + return; - d->mSortOrder.setGroupSortDirection( ord ); - Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, - d->mStorageUsesPrivateSortOrder ); + d->mSortOrder.setGroupSortDirection( ord ); + Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, + d->mStorageUsesPrivateSortOrder ); - d->mView->reload(); + d->mView->reload(); } void Widget::resetFilter() { - delete d->mFilter; - d->mFilter = 0; - d->mView->model()->setFilter( 0 ); - d->quickSearchLine->resetFilter(); + delete d->mFilter; + d->mFilter = 0; + d->mView->model()->setFilter( 0 ); + d->quickSearchLine->resetFilter(); } void Widget::slotViewHeaderSectionClicked( int logicalIndex ) { - if ( !d->mTheme ) - return; + if ( !d->mTheme ) + return; - if ( !d->mAggregation ) - return; + if ( !d->mAggregation ) + return; - if ( logicalIndex >= d->mTheme->columns().count() ) - return; + if ( logicalIndex >= d->mTheme->columns().count() ) + return; - if ( !d->mStorageModel ) - return; + if ( !d->mStorageModel ) + return; - const Theme::Column * column = d->mTheme->column( logicalIndex ); - if ( !column ) - return; // should never happen... + const Theme::Column * column = d->mTheme->column( logicalIndex ); + if ( !column ) + return; // should never happen... - if ( column->messageSorting() == SortOrder::NoMessageSorting ) - return; // this is a null op. + if ( column->messageSorting() == SortOrder::NoMessageSorting ) + return; // this is a null op. - if ( d->mSortOrder.messageSorting() == column->messageSorting() ) - { - // switch sort direction - if ( d->mSortOrder.messageSortDirection() == SortOrder::Ascending ) - d->switchMessageSorting( d->mSortOrder.messageSorting(), SortOrder::Descending, logicalIndex ); - else - d->switchMessageSorting( d->mSortOrder.messageSorting(), SortOrder::Ascending, logicalIndex ); - } else { - // keep sort direction but switch sort order - d->switchMessageSorting( column->messageSorting(), d->mSortOrder.messageSortDirection(), logicalIndex ); - } - Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, - d->mStorageUsesPrivateSortOrder ); + if ( d->mSortOrder.messageSorting() == column->messageSorting() ) + { + // switch sort direction + if ( d->mSortOrder.messageSortDirection() == SortOrder::Ascending ) + d->switchMessageSorting( d->mSortOrder.messageSorting(), SortOrder::Descending, logicalIndex ); + else + d->switchMessageSorting( d->mSortOrder.messageSorting(), SortOrder::Ascending, logicalIndex ); + } else { + // keep sort direction but switch sort order + d->switchMessageSorting( column->messageSorting(), d->mSortOrder.messageSortDirection(), logicalIndex ); + } + Manager::instance()->saveSortOrderForStorageModel( d->mStorageModel, d->mSortOrder, + d->mStorageUsesPrivateSortOrder ); - d->mView->reload(); + d->mView->reload(); } void Widget::themesChanged() { - d->setDefaultThemeForStorageModel( d->mStorageModel ); + d->setDefaultThemeForStorageModel( d->mStorageModel ); - d->mView->reload(); + d->mView->reload(); } void Widget::aggregationsChanged() { - d->setDefaultAggregationForStorageModel( d->mStorageModel ); - d->checkSortOrder( d->mStorageModel ); + d->setDefaultAggregationForStorageModel( d->mStorageModel ); + d->checkSortOrder( d->mStorageModel ); - d->mView->reload(); + d->mView->reload(); } void Widget::fillMessageTagCombo() { - // nothing here: must be overridden in derived classes - setCurrentStatusFilterItem(); + // nothing here: must be overridden in derived classes + setCurrentStatusFilterItem(); } void Widget::tagIdSelected( const QVariant& data ) { - QString tagId = data.toString(); + QString tagId = data.toString(); - if ( tagId.isEmpty() ) { - if ( d->mFilter ){ - if ( d->mFilter->isEmpty() ) { - resetFilter(); - return; - } + if ( tagId.isEmpty() ) { + if ( d->mFilter ){ + if ( d->mFilter->isEmpty() ) { + resetFilter(); + return; + } + } + } else { + if ( !d->mFilter ) + d->mFilter = new Filter(); + d->mFilter->setTagId( tagId ); } - } else { - if ( !d->mFilter ) - d->mFilter = new Filter(); - d->mFilter->setTagId( tagId ); - } - d->mView->model()->setFilter( d->mFilter ); + d->mView->model()->setFilter( d->mFilter ); } void Widget::statusSelected( int index ) @@ -928,22 +928,22 @@ void Widget::searchEditTextEdited() { - // This slot is called whenever the user edits the search QLineEdit. - // Since the user is likely to type more than one character - // so we start the real search after a short delay in order to catch - // multiple textEdited() signals. - - if ( !d->mSearchTimer ) - { - d->mSearchTimer = new QTimer( this ); - connect( d->mSearchTimer, SIGNAL(timeout()), - SLOT(searchTimerFired()) ); - } else { - d->mSearchTimer->stop(); // eventually - } + // This slot is called whenever the user edits the search QLineEdit. + // Since the user is likely to type more than one character + // so we start the real search after a short delay in order to catch + // multiple textEdited() signals. + + if ( !d->mSearchTimer ) + { + d->mSearchTimer = new QTimer( this ); + connect( d->mSearchTimer, SIGNAL(timeout()), + SLOT(searchTimerFired()) ); + } else { + d->mSearchTimer->stop(); // eventually + } - d->mSearchTimer->setSingleShot( true ); - d->mSearchTimer->start( 1000 ); + d->mSearchTimer->setSingleShot( true ); + d->mSearchTimer->start( 1000 ); } void Widget::slotStatusButtonsClicked() @@ -951,23 +951,23 @@ // We also arbitrairly set tagId to an empty string, though we *could* allow filtering // by status AND tag... if ( d->mFilter ) - d->mFilter->setTagId( QString() ); + d->mFilter->setTagId( QString() ); QList lst = d->quickSearchLine->status(); if ( lst.isEmpty() ) { - if ( d->mFilter ) { - d->mFilter->setStatus( lst ); - if ( d->mFilter->isEmpty() ) { - qDebug()<<" RESET FILTER"; - resetFilter(); - return; + if ( d->mFilter ) { + d->mFilter->setStatus( lst ); + if ( d->mFilter->isEmpty() ) { + qDebug()<<" RESET FILTER"; + resetFilter(); + return; + } } - } } else { - // don't have this status bit - if ( !d->mFilter ) - d->mFilter = new Filter(); - d->mFilter->setStatus( lst ); + // don't have this status bit + if ( !d->mFilter ) + d->mFilter = new Filter(); + d->mFilter->setStatus( lst ); } d->mView->model()->setFilter( d->mFilter ); @@ -975,34 +975,34 @@ void Widget::searchTimerFired() { - // A search is pending. + // A search is pending. - if ( d->mSearchTimer ) - d->mSearchTimer->stop(); + if ( d->mSearchTimer ) + d->mSearchTimer->stop(); - if ( !d->mFilter ) - d->mFilter = new Filter(); + if ( !d->mFilter ) + d->mFilter = new Filter(); - const QString text = d->quickSearchLine->searchEdit()->text(); + const QString text = d->quickSearchLine->searchEdit()->text(); - d->mFilter->setCurrentFolder( d->mCurrentFolder ); - d->mFilter->setSearchString( text, d->quickSearchLine->searchOptions() ); - if ( d->mFilter->isEmpty() ) { - resetFilter(); - return; - } + d->mFilter->setCurrentFolder( d->mCurrentFolder ); + d->mFilter->setSearchString( text, d->quickSearchLine->searchOptions() ); + if ( d->mFilter->isEmpty() ) { + resetFilter(); + return; + } - d->mView->model()->setFilter( d->mFilter ); + d->mView->model()->setFilter( d->mFilter ); } void Widget::searchEditClearButtonClicked() { - if ( !d->mFilter ) - return; + if ( !d->mFilter ) + return; - resetFilter(); + resetFilter(); - d->mView->scrollTo( d->mView->currentIndex(), QAbstractItemView::PositionAtCenter ); + d->mView->scrollTo( d->mView->currentIndex(), QAbstractItemView::PositionAtCenter ); } void Widget::viewMessageSelected( MessageItem * ) @@ -1051,33 +1051,33 @@ void Widget::viewMessageStatusChangeRequest( MessageItem *msg, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear ) { - Q_UNUSED( msg ); - Q_UNUSED( set ); - Q_UNUSED( clear ); + Q_UNUSED( msg ); + Q_UNUSED( set ); + Q_UNUSED( clear ); } void Widget::focusQuickSearch() { - d->quickSearchLine->focusQuickSearch(); + d->quickSearchLine->focusQuickSearch(); } bool Widget::isThreaded() const { - return d->mView->isThreaded(); + return d->mView->isThreaded(); } bool Widget::selectionEmpty() const { - return d->mView->selectionEmpty(); + return d->mView->selectionEmpty(); } void Widget::setCurrentFolder( const Akonadi::Collection &collection ) { - d->mCurrentFolder = collection; + d->mCurrentFolder = collection; } bool Widget::searchEditHasFocus() const { - return d->quickSearchLine->searchEdit()->hasFocus(); + return d->quickSearchLine->searchEdit()->hasFocus(); } diff -Nru kdepim-4.12.97/messagelist/core/widgetbase.h kdepim-4.13.0/messagelist/core/widgetbase.h --- kdepim-4.12.97/messagelist/core/widgetbase.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/core/widgetbase.h 2014-04-10 07:40:20.000000000 +0000 @@ -38,8 +38,8 @@ namespace Akonadi { - class Collection; - class MessageStatus; +class Collection; +class MessageStatus; } namespace MessageList @@ -59,101 +59,101 @@ */ class MESSAGELIST_EXPORT Widget : public QWidget { - friend class View; + friend class View; - Q_OBJECT + Q_OBJECT public: - explicit Widget( QWidget *parent ); - ~Widget(); + explicit Widget( QWidget *parent ); + ~Widget(); - /** + /** * Sets the storage model for this Widget. * * Pre-selection is the action of automatically selecting a message just after the folder * has finished loading. See Model::setStorageModel() for more information. */ - void setStorageModel( StorageModel * storageModel, PreSelectionMode preSelectionMode = PreSelectLastSelected ); + void setStorageModel( StorageModel * storageModel, PreSelectionMode preSelectionMode = PreSelectLastSelected ); - /** + /** * Returns the StorageModel currently set. May be 0. */ - StorageModel *storageModel() const; + StorageModel *storageModel() const; - /** + /** * Returns the search line of this widget. Can be 0 if the quick search * is disabled in the global configuration. */ - KLineEdit *quickSearch() const; + KLineEdit *quickSearch() const; - /** + /** * Returns the View attached to this Widget. Never 0. */ - View *view() const; + View *view() const; - /** + /** * Returns the current MessageItem in the current folder. * May return 0 if there is no current message or no current folder. */ - Core::MessageItem * currentMessageItem() const; + Core::MessageItem * currentMessageItem() const; - /** + /** * Returns the Akonadi::MessageStatus in the current quicksearch field. */ - QList currentFilterStatus() const; + QList currentFilterStatus() const; - /** + /** * Returns the search term in the current quicksearch field. */ - QString currentFilterSearchString() const; + QString currentFilterSearchString() const; - /** + /** * Returns the id of the MessageItem::Tag currently set in the quicksearch field. */ - QString currentFilterTagId() const; + QString currentFilterTagId() const; - /** + /** * Sets the focus on the quick search line of the currently active tab. */ - void focusQuickSearch(); + void focusQuickSearch(); - /** + /** * Returns true if the current Aggregation is threaded, false otherwise * (or if there is no current Aggregation). */ - bool isThreaded() const; - /** + bool isThreaded() const; + /** * Fast function that determines if the selection is empty */ - bool selectionEmpty() const; + bool selectionEmpty() const; - /** + /** * Sets the current folder. */ - void setCurrentFolder( const Akonadi::Collection &collection ); + void setCurrentFolder( const Akonadi::Collection &collection ); - void saveCurrentSelection(); + void saveCurrentSelection(); - bool searchEditHasFocus() const; + bool searchEditHasFocus() const; - void sortOrderMenuAboutToShow(KMenu *menu); - void themeMenuAboutToShow(KMenu *menu); - void aggregationMenuAboutToShow(KMenu *menu); + void sortOrderMenuAboutToShow(KMenu *menu); + void themeMenuAboutToShow(KMenu *menu); + void aggregationMenuAboutToShow(KMenu *menu); public slots: - /** + /** * This is called to setup the status filter's KComboBox. */ - void populateStatusFilterCombo(); + void populateStatusFilterCombo(); - /** + /** * Shows or hides the quicksearch field, the filter combobox and the toolbutton for advanced search. */ - void changeQuicksearchVisibility(bool); + void changeQuicksearchVisibility(bool); protected: - /** + /** * Called when the "Message Status/Tag" filter menu is opened by the user. * You may override this function in order to add some "custom tag" entries * to the menu. The entries should be placed in a QActionGroup which should be returned @@ -163,123 +163,123 @@ * * Once the tag retrieval is complete call setCurrentStatusFilterItem() */ - virtual void fillMessageTagCombo(); + virtual void fillMessageTagCombo(); - void addMessageTagItem(const QPixmap &, const QString &, const QVariant &); + void addMessageTagItem(const QPixmap &, const QString &, const QVariant &); - /** + /** * Must be called by fillMessageTagCombo() */ - void setCurrentStatusFilterItem(); + void setCurrentStatusFilterItem(); - /** + /** * This is called by View when a message is single-clicked (thus selected and made current) */ - virtual void viewMessageSelected( MessageItem *msg ); + virtual void viewMessageSelected( MessageItem *msg ); - /** + /** * This is called by View when a message is double-clicked or activated by other input means */ - virtual void viewMessageActivated( MessageItem *msg ); + virtual void viewMessageActivated( MessageItem *msg ); - /** + /** * This is called by View when selection changes. */ - virtual void viewSelectionChanged(); + virtual void viewSelectionChanged(); - /** + /** * This is called by View when a message is right clicked. */ - virtual void viewMessageListContextPopupRequest( const QList< MessageItem * > &selectedItems, const QPoint &globalPos ); + virtual void viewMessageListContextPopupRequest( const QList< MessageItem * > &selectedItems, const QPoint &globalPos ); - /** + /** * This is called by View when a group header is right clicked. */ - virtual void viewGroupHeaderContextPopupRequest( GroupHeaderItem *group, const QPoint &globalPos ); + virtual void viewGroupHeaderContextPopupRequest( GroupHeaderItem *group, const QPoint &globalPos ); - /** + /** * This is called by View when a drag enter event is received */ - virtual void viewDragEnterEvent( QDragEnterEvent * e ); + virtual void viewDragEnterEvent( QDragEnterEvent * e ); - /** + /** * This is called by View when a drag move event is received */ - virtual void viewDragMoveEvent( QDragMoveEvent * e ); + virtual void viewDragMoveEvent( QDragMoveEvent * e ); - /** + /** * This is called by View when a drop event is received */ - virtual void viewDropEvent( QDropEvent * e ); + virtual void viewDropEvent( QDropEvent * e ); - /** + /** * This is called by View when a drag can possibly be started */ - virtual void viewStartDragRequest(); + virtual void viewStartDragRequest(); - /** + /** * This is called by View when a message item is manipulated by the user * in a way that it's status should change. (e.g, by clicking on a status icon, for example). */ - virtual void viewMessageStatusChangeRequest( MessageItem *msg, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear ); + virtual void viewMessageStatusChangeRequest( MessageItem *msg, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear ); - /** + /** * This is called by View to signal a start of a (possibly lengthy) job batch. */ - virtual void viewJobBatchStarted(); + virtual void viewJobBatchStarted(); - /** + /** * This is called by View to signal the end of a (possibly lengthy) job batch. */ - virtual void viewJobBatchTerminated(); + virtual void viewJobBatchTerminated(); - void tagIdSelected(const QVariant &data ); + void tagIdSelected(const QVariant &data ); Q_SIGNALS: - /** + /** * Notify the outside when updating the status bar with a message * could be useful */ - void statusMessage( const QString &message ); + void statusMessage( const QString &message ); protected slots: - /** + /** * This is called by Manager when the option sets stored within have changed. */ - void aggregationsChanged(); + void aggregationsChanged(); - /** + /** * This is called by Manager when the option sets stored within have changed. */ - void themesChanged(); + void themesChanged(); - void themeMenuAboutToShow(); - void aggregationMenuAboutToShow(); - void themeSelected( bool ); - void configureThemes(); - void setPrivateSortOrderForStorage(); - void aggregationSelected( bool ); - void statusSelected( int index ); - void searchEditTextEdited(); - void searchTimerFired(); - void searchEditClearButtonClicked(); - void sortOrderMenuAboutToShow(); - void messageSortingSelected( QAction *action ); - void messageSortDirectionSelected( QAction *action ); - void groupSortingSelected( QAction *action ); - void groupSortDirectionSelected( QAction *action ); - void resetFilter(); + void themeMenuAboutToShow(); + void aggregationMenuAboutToShow(); + void themeSelected( bool ); + void configureThemes(); + void setPrivateSortOrderForStorage(); + void aggregationSelected( bool ); + void statusSelected( int index ); + void searchEditTextEdited(); + void searchTimerFired(); + void searchEditClearButtonClicked(); + void sortOrderMenuAboutToShow(); + void messageSortingSelected( QAction *action ); + void messageSortDirectionSelected( QAction *action ); + void groupSortingSelected( QAction *action ); + void groupSortDirectionSelected( QAction *action ); + void resetFilter(); - /** + /** * Handles header section clicks switching the Aggregation MessageSorting on-the-fly. */ - void slotViewHeaderSectionClicked( int logicalIndex ); - void slotStatusButtonsClicked(); + void slotViewHeaderSectionClicked( int logicalIndex ); + void slotStatusButtonsClicked(); private: - class Private; - Private * const d; + class Private; + Private * const d; }; } // namespace Core diff -Nru kdepim-4.12.97/messagelist/messagelistutil.cpp kdepim-4.13.0/messagelist/messagelistutil.cpp --- kdepim-4.12.97/messagelist/messagelistutil.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/messagelistutil.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -30,77 +30,77 @@ QString MessageList::Util::messageSortingConfigName() { - return QLatin1String( "MessageSorting" ); + return QLatin1String( "MessageSorting" ); } QString MessageList::Util::messageSortDirectionConfigName() { - return QLatin1String( "MessageSortDirection" ); + return QLatin1String( "MessageSortDirection" ); } QString MessageList::Util::groupSortingConfigName() { - return QLatin1String( "GroupSorting" ); + return QLatin1String( "GroupSorting" ); } QString MessageList::Util::groupSortDirectionConfigName() { - return QLatin1String( "GroupSortDirection" ); + return QLatin1String( "GroupSortDirection" ); } QString MessageList::Util::messageUniqueIdConfigName() { - return QString::fromLatin1( "MessageUniqueIdForStorageModel%1" ); + return QString::fromLatin1( "MessageUniqueIdForStorageModel%1" ); } QString MessageList::Util::storageModelSortOrderGroup() { - return QLatin1String( "MessageListView::StorageModelSortOrder" ); + return QLatin1String( "MessageListView::StorageModelSortOrder" ); } QString MessageList::Util::storageModelThemesGroup() { - return QLatin1String( "MessageListView::StorageModelThemes" ); + return QLatin1String( "MessageListView::StorageModelThemes" ); } QString MessageList::Util::storageModelAggregationsGroup() { - return QLatin1String( "MessageListView::StorageModelAggregations" ); + return QLatin1String( "MessageListView::StorageModelAggregations" ); } QString MessageList::Util::setForStorageModelConfigName() { - return QString::fromLatin1( "SetForStorageModel%1" ); + return QString::fromLatin1( "SetForStorageModel%1" ); } QString MessageList::Util::storageModelSelectedMessageGroup() { - return QLatin1String( "MessageListView::StorageModelSelectedMessages" ); + return QLatin1String( "MessageListView::StorageModelSelectedMessages" ); } void MessageList::Util::deleteConfig( const QString& collectionId ) { - KConfigGroup confselectedMessage( Settings::self()->config(), - MessageList::Util::storageModelSelectedMessageGroup() ); - confselectedMessage.deleteEntry( MessageList::Util::messageUniqueIdConfigName().arg( collectionId ) ); - - KConfigGroup storageModelOrder( Settings::self()->config(), - MessageList::Util::storageModelSortOrderGroup() ); - storageModelOrder.deleteEntry( collectionId + groupSortDirectionConfigName() ); - storageModelOrder.deleteEntry( collectionId + groupSortingConfigName() ); - storageModelOrder.deleteEntry( collectionId + messageSortDirectionConfigName() ); - storageModelOrder.deleteEntry( collectionId + messageSortingConfigName() ); - - KConfigGroup storageModelTheme( Settings::self()->config(), - MessageList::Util::storageModelThemesGroup() ); - storageModelTheme.deleteEntry( collectionId + setForStorageModelConfigName() ); - - - KConfigGroup storageModelAggregation( Settings::self()->config(), - MessageList::Util::storageModelAggregationsGroup() ); - storageModelAggregation.deleteEntry( collectionId + setForStorageModelConfigName() ); + KConfigGroup confselectedMessage( Settings::self()->config(), + MessageList::Util::storageModelSelectedMessageGroup() ); + confselectedMessage.deleteEntry( MessageList::Util::messageUniqueIdConfigName().arg( collectionId ) ); + + KConfigGroup storageModelOrder( Settings::self()->config(), + MessageList::Util::storageModelSortOrderGroup() ); + storageModelOrder.deleteEntry( collectionId + groupSortDirectionConfigName() ); + storageModelOrder.deleteEntry( collectionId + groupSortingConfigName() ); + storageModelOrder.deleteEntry( collectionId + messageSortDirectionConfigName() ); + storageModelOrder.deleteEntry( collectionId + messageSortingConfigName() ); + + KConfigGroup storageModelTheme( Settings::self()->config(), + MessageList::Util::storageModelThemesGroup() ); + storageModelTheme.deleteEntry( collectionId + setForStorageModelConfigName() ); + + + KConfigGroup storageModelAggregation( Settings::self()->config(), + MessageList::Util::storageModelAggregationsGroup() ); + storageModelAggregation.deleteEntry( collectionId + setForStorageModelConfigName() ); } @@ -121,56 +121,56 @@ void MessageList::Util::fillViewMenu( KMenu * menu, QObject *receiver ) { - KMenu* sortingMenu = new KMenu( i18n( "Sorting" ), menu ); - sortingMenu->setIcon( KIcon( QLatin1String( "view-sort-ascending" ) ) ); - menu->addMenu( sortingMenu ); - QObject::connect( sortingMenu, SIGNAL(aboutToShow()), - receiver, SLOT(sortOrderMenuAboutToShow()) ); - - KMenu* aggregationMenu = new KMenu( i18n( "Aggregation" ), menu ); - aggregationMenu->setIcon( KIcon( QLatin1String( "view-process-tree" ) ) ); - menu->addMenu( aggregationMenu ); - QObject::connect( aggregationMenu, SIGNAL(aboutToShow()), - receiver, SLOT(aggregationMenuAboutToShow()) ); - - KMenu* themeMenu = new KMenu( i18n( "Theme" ), menu ); - themeMenu->setIcon( KIcon( QLatin1String( "preferences-desktop-theme" ) ) ); - menu->addMenu( themeMenu ); - QObject::connect( themeMenu, SIGNAL(aboutToShow()), - receiver, SLOT(themeMenuAboutToShow()) ); + KMenu* sortingMenu = new KMenu( i18n( "Sorting" ), menu ); + sortingMenu->setIcon( KIcon( QLatin1String( "view-sort-ascending" ) ) ); + menu->addMenu( sortingMenu ); + QObject::connect( sortingMenu, SIGNAL(aboutToShow()), + receiver, SLOT(sortOrderMenuAboutToShow()) ); + + KMenu* aggregationMenu = new KMenu( i18n( "Aggregation" ), menu ); + aggregationMenu->setIcon( KIcon( QLatin1String( "view-process-tree" ) ) ); + menu->addMenu( aggregationMenu ); + QObject::connect( aggregationMenu, SIGNAL(aboutToShow()), + receiver, SLOT(aggregationMenuAboutToShow()) ); + + KMenu* themeMenu = new KMenu( i18n( "Theme" ), menu ); + themeMenu->setIcon( KIcon( QLatin1String( "preferences-desktop-theme" ) ) ); + menu->addMenu( themeMenu ); + QObject::connect( themeMenu, SIGNAL(aboutToShow()), + receiver, SLOT(themeMenuAboutToShow()) ); } QString MessageList::Util::contentSummary( const Akonadi::Item &item ) { - if ( !item.hasPayload() ) { - return QString(); - } - - KMime::Message::Ptr message = item.payload(); - KMime::Content *textContent = message->textContent(); - if ( !textContent ) { - return QString(); - } - const QString content = textContent->decodedText( true, true ); - if ( content.isEmpty() ) { - return QString(); - } - - // Extract the first 5 non-empty, non-quoted lines from the content and return it - int numLines = 0; - const int maxLines = 5; - const QStringList lines = content.split( QLatin1Char( '\n' ) ); - QString ret; - foreach( const QString &line, lines ) { - const QString lineTrimmed = line.trimmed(); - const bool isQuoted = lineTrimmed.startsWith( QLatin1Char( '>' ) ) || lineTrimmed.startsWith( QLatin1Char( '|' ) ); - if ( !isQuoted && !lineTrimmed.isEmpty() ) { - ret += line + QLatin1Char( '\n' ); - numLines++; - if ( numLines >= maxLines ) - break; + if ( !item.hasPayload() ) { + return QString(); } - } - return Qt::escape(ret); + + KMime::Message::Ptr message = item.payload(); + KMime::Content *textContent = message->textContent(); + if ( !textContent ) { + return QString(); + } + const QString content = textContent->decodedText( true, true ); + if ( content.isEmpty() ) { + return QString(); + } + + // Extract the first 5 non-empty, non-quoted lines from the content and return it + int numLines = 0; + const int maxLines = 5; + const QStringList lines = content.split( QLatin1Char( '\n' ) ); + QString ret; + foreach( const QString &line, lines ) { + const QString lineTrimmed = line.trimmed(); + const bool isQuoted = lineTrimmed.startsWith( QLatin1Char( '>' ) ) || lineTrimmed.startsWith( QLatin1Char( '|' ) ); + if ( !isQuoted && !lineTrimmed.isEmpty() ) { + ret += line + QLatin1Char( '\n' ); + numLines++; + if ( numLines >= maxLines ) + break; + } + } + return Qt::escape(ret); } diff -Nru kdepim-4.12.97/messagelist/messagelistutil.h kdepim-4.13.0/messagelist/messagelistutil.h --- kdepim-4.12.97/messagelist/messagelistutil.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/messagelistutil.h 2014-04-10 07:40:20.000000000 +0000 @@ -24,31 +24,31 @@ #include namespace Akonadi { - class Item; +class Item; } class KMenu; namespace MessageList { namespace Util { - MESSAGELIST_EXPORT QString messageSortingConfigName(); - MESSAGELIST_EXPORT QString messageSortDirectionConfigName(); - MESSAGELIST_EXPORT QString groupSortingConfigName(); - MESSAGELIST_EXPORT QString groupSortDirectionConfigName(); - MESSAGELIST_EXPORT QString messageUniqueIdConfigName(); - MESSAGELIST_EXPORT QString storageModelSortOrderGroup(); - MESSAGELIST_EXPORT QString storageModelThemesGroup(); - MESSAGELIST_EXPORT QString storageModelAggregationsGroup(); - MESSAGELIST_EXPORT QString setForStorageModelConfigName(); - MESSAGELIST_EXPORT QString storageModelSelectedMessageGroup(); - MESSAGELIST_EXPORT void deleteConfig( const QString& collectionId ); - MESSAGELIST_EXPORT QColor unreadDefaultMessageColor(); - MESSAGELIST_EXPORT QColor importantDefaultMessageColor(); - MESSAGELIST_EXPORT QColor todoDefaultMessageColor(); - MESSAGELIST_EXPORT void fillViewMenu( KMenu * menu, QObject *receiver ); +MESSAGELIST_EXPORT QString messageSortingConfigName(); +MESSAGELIST_EXPORT QString messageSortDirectionConfigName(); +MESSAGELIST_EXPORT QString groupSortingConfigName(); +MESSAGELIST_EXPORT QString groupSortDirectionConfigName(); +MESSAGELIST_EXPORT QString messageUniqueIdConfigName(); +MESSAGELIST_EXPORT QString storageModelSortOrderGroup(); +MESSAGELIST_EXPORT QString storageModelThemesGroup(); +MESSAGELIST_EXPORT QString storageModelAggregationsGroup(); +MESSAGELIST_EXPORT QString setForStorageModelConfigName(); +MESSAGELIST_EXPORT QString storageModelSelectedMessageGroup(); +MESSAGELIST_EXPORT void deleteConfig( const QString& collectionId ); +MESSAGELIST_EXPORT QColor unreadDefaultMessageColor(); +MESSAGELIST_EXPORT QColor importantDefaultMessageColor(); +MESSAGELIST_EXPORT QColor todoDefaultMessageColor(); +MESSAGELIST_EXPORT void fillViewMenu( KMenu * menu, QObject *receiver ); - /// Returns the first few lines of the actual email text if available. - MESSAGELIST_EXPORT QString contentSummary( const Akonadi::Item &item ); +/// Returns the first few lines of the actual email text if available. +MESSAGELIST_EXPORT QString contentSummary( const Akonadi::Item &item ); } } diff -Nru kdepim-4.12.97/messagelist/pane.cpp kdepim-4.13.0/messagelist/pane.cpp --- kdepim-4.12.97/messagelist/pane.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/pane.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -50,64 +50,64 @@ class Pane::Private { public: - Private( Pane *owner ) - : q( owner ), - mXmlGuiClient( 0 ), - mActionMenu( 0 ), - mModel( 0 ), - mSelectionModel( 0 ), - mPreSelectionMode( Core::PreSelectLastSelected ), - mNewTabButton( 0 ), - mCloseTabButton( 0 ), - mCloseTabAction( 0 ), - mActivateNextTabAction( 0 ), - mActivatePreviousTabAction( 0 ), - mMoveTabLeftAction( 0 ), - mMoveTabRightAction( 0 ), - mPreferEmptyTab( false ), - mMaxTabCreated( 0 ) - { } - - void onSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected ); - void onNewTabClicked(); - void onCloseTabClicked(); - void activateTab(); - void closeTab( QWidget * ); - void onCurrentTabChanged(); - void onTabContextMenuRequest( const QPoint &pos ); - void activateNextTab(); - void activatePreviousTab(); - void moveTabLeft(); - void moveTabRight(); - void moveTabBackward(); - void moveTabForward(); - void changeQuicksearchVisibility(bool); - void addActivateTabAction(int i); - QItemSelection mapSelectionToSource( const QItemSelection &selection ) const; - QItemSelection mapSelectionFromSource( const QItemSelection &selection ) const; - void updateTabControls(); - - Pane * const q; - - KXMLGUIClient *mXmlGuiClient; - KActionMenu *mActionMenu; - - QAbstractItemModel *mModel; - QItemSelectionModel *mSelectionModel; - Core::PreSelectionMode mPreSelectionMode; - - QHash mWidgetSelectionHash; - QList mProxyStack; - - QToolButton *mNewTabButton; - QToolButton *mCloseTabButton; - KAction *mCloseTabAction; - KAction *mActivateNextTabAction; - KAction *mActivatePreviousTabAction; - KAction *mMoveTabLeftAction; - KAction *mMoveTabRightAction; - bool mPreferEmptyTab; - int mMaxTabCreated; + Private( Pane *owner ) + : q( owner ), + mXmlGuiClient( 0 ), + mActionMenu( 0 ), + mModel( 0 ), + mSelectionModel( 0 ), + mPreSelectionMode( Core::PreSelectLastSelected ), + mNewTabButton( 0 ), + mCloseTabButton( 0 ), + mCloseTabAction( 0 ), + mActivateNextTabAction( 0 ), + mActivatePreviousTabAction( 0 ), + mMoveTabLeftAction( 0 ), + mMoveTabRightAction( 0 ), + mPreferEmptyTab( false ), + mMaxTabCreated( 0 ) + { } + + void onSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected ); + void onNewTabClicked(); + void onCloseTabClicked(); + void activateTab(); + void closeTab( QWidget * ); + void onCurrentTabChanged(); + void onTabContextMenuRequest( const QPoint &pos ); + void activateNextTab(); + void activatePreviousTab(); + void moveTabLeft(); + void moveTabRight(); + void moveTabBackward(); + void moveTabForward(); + void changeQuicksearchVisibility(bool); + void addActivateTabAction(int i); + QItemSelection mapSelectionToSource( const QItemSelection &selection ) const; + QItemSelection mapSelectionFromSource( const QItemSelection &selection ) const; + void updateTabControls(); + + Pane * const q; + + KXMLGUIClient *mXmlGuiClient; + KActionMenu *mActionMenu; + + QAbstractItemModel *mModel; + QItemSelectionModel *mSelectionModel; + Core::PreSelectionMode mPreSelectionMode; + + QHash mWidgetSelectionHash; + QList mProxyStack; + + QToolButton *mNewTabButton; + QToolButton *mCloseTabButton; + KAction *mCloseTabAction; + KAction *mActivateNextTabAction; + KAction *mActivatePreviousTabAction; + KAction *mMoveTabLeftAction; + KAction *mMoveTabRightAction; + bool mPreferEmptyTab; + int mMaxTabCreated; }; } // namespace MessageList @@ -117,165 +117,165 @@ Pane::Pane( bool restoreSession, QAbstractItemModel *model, QItemSelectionModel *selectionModel, QWidget *parent ) - : KTabWidget( parent ), d( new Private( this ) ) + : KTabWidget( parent ), d( new Private( this ) ) { - setDocumentMode( true ); - d->mModel = model; - d->mSelectionModel = selectionModel; - - // Build the proxy stack - const QAbstractProxyModel *proxyModel = qobject_cast( d->mSelectionModel->model() ); - - while (proxyModel) { - if (static_cast(proxyModel) == d->mModel) { - break; - } + setDocumentMode( true ); + d->mModel = model; + d->mSelectionModel = selectionModel; + + // Build the proxy stack + const QAbstractProxyModel *proxyModel = qobject_cast( d->mSelectionModel->model() ); + + while (proxyModel) { + if (static_cast(proxyModel) == d->mModel) { + break; + } - d->mProxyStack << proxyModel; - const QAbstractProxyModel *nextProxyModel = qobject_cast(proxyModel->sourceModel()); + d->mProxyStack << proxyModel; + const QAbstractProxyModel *nextProxyModel = qobject_cast(proxyModel->sourceModel()); - if (!nextProxyModel) { - // It's the final model in the chain, so it is necessarily the sourceModel. - Q_ASSERT(qobject_cast(proxyModel->sourceModel()) == d->mModel); - break; - } - proxyModel = nextProxyModel; - } // Proxy stack done + if (!nextProxyModel) { + // It's the final model in the chain, so it is necessarily the sourceModel. + Q_ASSERT(qobject_cast(proxyModel->sourceModel()) == d->mModel); + break; + } + proxyModel = nextProxyModel; + } // Proxy stack done - d->mNewTabButton = new QToolButton( this ); - d->mNewTabButton->setIcon( KIcon( QLatin1String( "tab-new" ) ) ); - d->mNewTabButton->adjustSize(); - d->mNewTabButton->setToolTip( i18nc("@info:tooltip", "Open a new tab")); + d->mNewTabButton = new QToolButton( this ); + d->mNewTabButton->setIcon( KIcon( QLatin1String( "tab-new" ) ) ); + d->mNewTabButton->adjustSize(); + d->mNewTabButton->setToolTip( i18nc("@info:tooltip", "Open a new tab")); #ifndef QT_NO_ACCESSIBILITY - d->mNewTabButton->setAccessibleName( i18n( "New tab" ) ); + d->mNewTabButton->setAccessibleName( i18n( "New tab" ) ); #endif - setCornerWidget( d->mNewTabButton, Qt::TopLeftCorner ); - connect( d->mNewTabButton, SIGNAL(clicked()), - SLOT(onNewTabClicked()) ); - - d->mCloseTabButton = new QToolButton( this ); - d->mCloseTabButton->setIcon( KIcon( QLatin1String( "tab-close" ) ) ); - d->mCloseTabButton->adjustSize(); - d->mCloseTabButton->setToolTip( i18nc("@info:tooltip", "Close the current tab")); + setCornerWidget( d->mNewTabButton, Qt::TopLeftCorner ); + connect( d->mNewTabButton, SIGNAL(clicked()), + SLOT(onNewTabClicked()) ); + + d->mCloseTabButton = new QToolButton( this ); + d->mCloseTabButton->setIcon( KIcon( QLatin1String( "tab-close" ) ) ); + d->mCloseTabButton->adjustSize(); + d->mCloseTabButton->setToolTip( i18nc("@info:tooltip", "Close the current tab")); #ifndef QT_NO_ACCESSIBILITY - d->mCloseTabButton->setAccessibleName( i18n( "Close tab" ) ); + d->mCloseTabButton->setAccessibleName( i18n( "Close tab" ) ); #endif - setCornerWidget( d->mCloseTabButton, Qt::TopRightCorner ); - connect( d->mCloseTabButton, SIGNAL(clicked()), - SLOT(onCloseTabClicked()) ); - - setTabsClosable( Core::Settings::self()->tabsHaveCloseButton() ); - connect( this, SIGNAL(closeRequest(QWidget*)), SLOT(closeTab(QWidget*)) ); - - readConfig(restoreSession); - setMovable( true ); - - connect( d->mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - this, SLOT(onSelectionChanged(QItemSelection,QItemSelection)) ); - connect( this, SIGNAL(currentChanged(int)), - this, SLOT(onCurrentTabChanged()) ); - - setContextMenuPolicy( Qt::CustomContextMenu ); - connect( this, SIGNAL(customContextMenuRequested(QPoint)), - this, SLOT(onTabContextMenuRequest(QPoint)) ); - - connect( Core::Settings::self(), SIGNAL(configChanged()), - this, SLOT(updateTabControls()) ); - - connect( this, SIGNAL(mouseDoubleClick()), - this, SLOT(createNewTab()) ); - - connect( this, SIGNAL(mouseMiddleClick(QWidget*)), - this, SLOT(closeTab(QWidget*)) ); - tabBar()->installEventFilter( this ); + setCornerWidget( d->mCloseTabButton, Qt::TopRightCorner ); + connect( d->mCloseTabButton, SIGNAL(clicked()), + SLOT(onCloseTabClicked()) ); + + setTabsClosable( Core::Settings::self()->tabsHaveCloseButton() ); + connect( this, SIGNAL(closeRequest(QWidget*)), SLOT(closeTab(QWidget*)) ); + + readConfig(restoreSession); + setMovable( true ); + + connect( d->mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(onSelectionChanged(QItemSelection,QItemSelection)) ); + connect( this, SIGNAL(currentChanged(int)), + this, SLOT(onCurrentTabChanged()) ); + + setContextMenuPolicy( Qt::CustomContextMenu ); + connect( this, SIGNAL(customContextMenuRequested(QPoint)), + this, SLOT(onTabContextMenuRequest(QPoint)) ); + + connect( Core::Settings::self(), SIGNAL(configChanged()), + this, SLOT(updateTabControls()) ); + + connect( this, SIGNAL(mouseDoubleClick()), + this, SLOT(createNewTab()) ); + + connect( this, SIGNAL(mouseMiddleClick(QWidget*)), + this, SLOT(closeTab(QWidget*)) ); + tabBar()->installEventFilter( this ); } Pane::~Pane() { - writeConfig(true); - delete d; + writeConfig(true); + delete d; } void Pane::Private::addActivateTabAction(int i) { - QString actionname; - actionname.sprintf("activate_tab_%02d", i); - KAction *action = new KAction( i18n("Activate Tab %1", i), q); - action->setShortcut( QKeySequence( QString::fromLatin1( "Alt+%1" ).arg( i ) ) ); - mXmlGuiClient->actionCollection()->addAction( actionname, action ); - connect( action, SIGNAL(triggered(bool)),q, SLOT(activateTab()) ); + QString actionname; + actionname.sprintf("activate_tab_%02d", i); + KAction *action = new KAction( i18n("Activate Tab %1", i), q); + action->setShortcut( QKeySequence( QString::fromLatin1( "Alt+%1" ).arg( i ) ) ); + mXmlGuiClient->actionCollection()->addAction( actionname, action ); + connect( action, SIGNAL(triggered(bool)),q, SLOT(activateTab()) ); } void Pane::setXmlGuiClient( KXMLGUIClient *xmlGuiClient ) { - d->mXmlGuiClient = xmlGuiClient; - - KToggleAction * const showHideQuicksearch = new KToggleAction( i18n( "Show Quick Search Bar" ), this ); - showHideQuicksearch->setShortcut( Qt::CTRL + Qt::Key_H ); - showHideQuicksearch->setChecked( Core::Settings::showQuickSearch() ); + d->mXmlGuiClient = xmlGuiClient; - d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "show_quick_search" ), showHideQuicksearch ); - connect( showHideQuicksearch, SIGNAL(triggered(bool)), this, SLOT(changeQuicksearchVisibility(bool)) ); + KToggleAction * const showHideQuicksearch = new KToggleAction( i18n( "Show Quick Search Bar" ), this ); + showHideQuicksearch->setShortcut( Qt::CTRL + Qt::Key_H ); + showHideQuicksearch->setChecked( Core::Settings::showQuickSearch() ); + d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "show_quick_search" ), showHideQuicksearch ); + connect( showHideQuicksearch, SIGNAL(triggered(bool)), this, SLOT(changeQuicksearchVisibility(bool)) ); - for ( int i=0; i( widget( i ) ); - w->setXmlGuiClient( d->mXmlGuiClient ); - } - // Setup "View->Message List" actions. - if ( xmlGuiClient ) { - if ( d->mActionMenu ) { - d->mXmlGuiClient->actionCollection()->removeAction( d->mActionMenu ); - } - d->mActionMenu = new KActionMenu( KIcon(), i18n( "Message List" ), this ); - d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "view_message_list" ), d->mActionMenu ); - MessageList::Util::fillViewMenu( d->mActionMenu->menu(), this ); - - d->mActionMenu->addSeparator(); - - KAction *action = new KAction( i18n("Create New Tab"), this ); - action->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_O ) ); - d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "create_new_tab" ), action ); - connect( action, SIGNAL(triggered(bool)), SLOT(onNewTabClicked()) ); - d->mActionMenu->addAction( action ); - - d->mMaxTabCreated = count(); - for (int i=1;i<10 && i<=count();++i) { - d->addActivateTabAction(i); + for ( int i=0; i( widget( i ) ); + w->setXmlGuiClient( d->mXmlGuiClient ); } + // Setup "View->Message List" actions. + if ( xmlGuiClient ) { + if ( d->mActionMenu ) { + d->mXmlGuiClient->actionCollection()->removeAction( d->mActionMenu ); + } + d->mActionMenu = new KActionMenu( KIcon(), i18n( "Message List" ), this ); + d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "view_message_list" ), d->mActionMenu ); + MessageList::Util::fillViewMenu( d->mActionMenu->menu(), this ); + + d->mActionMenu->addSeparator(); + + KAction *action = new KAction( i18n("Create New Tab"), this ); + action->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_O ) ); + d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "create_new_tab" ), action ); + connect( action, SIGNAL(triggered(bool)), SLOT(onNewTabClicked()) ); + d->mActionMenu->addAction( action ); + + d->mMaxTabCreated = count(); + for (int i=1;i<10 && i<=count();++i) { + d->addActivateTabAction(i); + } + - d->mCloseTabAction = new KAction( i18n("Close Tab"), this ); - d->mCloseTabAction->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_W ) ); - d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "close_current_tab" ), d->mCloseTabAction ); - connect( d->mCloseTabAction, SIGNAL(triggered(bool)), SLOT(onCloseTabClicked()) ); - d->mActionMenu->addAction( d->mCloseTabAction ); - d->mCloseTabAction->setEnabled( false ); - - d->mActivateNextTabAction = new KAction( i18n("Activate Next Tab"),this ); - d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "activate_next_tab" ), d->mActivateNextTabAction ); - d->mActivateNextTabAction->setEnabled( false ); - connect( d->mActivateNextTabAction, SIGNAL(triggered(bool)), SLOT(activateNextTab()) ); - - d->mActivatePreviousTabAction = new KAction( i18n("Activate Previous Tab"),this ); - d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "activate_previous_tab" ), d->mActivatePreviousTabAction ); - d->mActivatePreviousTabAction->setEnabled( false ); - connect( d->mActivatePreviousTabAction, SIGNAL(triggered(bool)), SLOT(activatePreviousTab()) ); - - - d->mMoveTabLeftAction = new KAction( i18n("Move Tab Left"),this ); - d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "move_tab_left" ), d->mMoveTabLeftAction ); - d->mMoveTabLeftAction->setEnabled( false ); - connect( d->mMoveTabLeftAction, SIGNAL(triggered(bool)), SLOT(moveTabLeft()) ); - - d->mMoveTabRightAction = new KAction( i18n("Move Tab Right"),this ); - d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "move_tab_right" ), d->mMoveTabRightAction ); - d->mMoveTabRightAction->setEnabled( false ); - connect( d->mMoveTabRightAction, SIGNAL(triggered(bool)), SLOT(moveTabRight()) ); - } + d->mCloseTabAction = new KAction( i18n("Close Tab"), this ); + d->mCloseTabAction->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_W ) ); + d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "close_current_tab" ), d->mCloseTabAction ); + connect( d->mCloseTabAction, SIGNAL(triggered(bool)), SLOT(onCloseTabClicked()) ); + d->mActionMenu->addAction( d->mCloseTabAction ); + d->mCloseTabAction->setEnabled( false ); + + d->mActivateNextTabAction = new KAction( i18n("Activate Next Tab"),this ); + d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "activate_next_tab" ), d->mActivateNextTabAction ); + d->mActivateNextTabAction->setEnabled( false ); + connect( d->mActivateNextTabAction, SIGNAL(triggered(bool)), SLOT(activateNextTab()) ); + + d->mActivatePreviousTabAction = new KAction( i18n("Activate Previous Tab"),this ); + d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "activate_previous_tab" ), d->mActivatePreviousTabAction ); + d->mActivatePreviousTabAction->setEnabled( false ); + connect( d->mActivatePreviousTabAction, SIGNAL(triggered(bool)), SLOT(activatePreviousTab()) ); + + + d->mMoveTabLeftAction = new KAction( i18n("Move Tab Left"),this ); + d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "move_tab_left" ), d->mMoveTabLeftAction ); + d->mMoveTabLeftAction->setEnabled( false ); + connect( d->mMoveTabLeftAction, SIGNAL(triggered(bool)), SLOT(moveTabLeft()) ); + + d->mMoveTabRightAction = new KAction( i18n("Move Tab Right"),this ); + d->mXmlGuiClient->actionCollection()->addAction( QLatin1String( "move_tab_right" ), d->mMoveTabRightAction ); + d->mMoveTabRightAction->setEnabled( false ); + connect( d->mMoveTabRightAction, SIGNAL(triggered(bool)), SLOT(moveTabRight()) ); + } } bool Pane::selectNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, @@ -283,16 +283,16 @@ bool centerItem, bool loop ) { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - if ( w->view()->model()->isLoading() ) - return true; + if ( w ) { + if ( w->view()->model()->isLoading() ) + return true; - return w->selectNextMessageItem( messageTypeFilter, existingSelectionBehaviour, centerItem, loop ); - } else { - return false; - } + return w->selectNextMessageItem( messageTypeFilter, existingSelectionBehaviour, centerItem, loop ); + } else { + return false; + } } bool Pane::selectPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, @@ -300,645 +300,645 @@ bool centerItem, bool loop ) { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - if ( w->view()->model()->isLoading() ) - return true; + if ( w ) { + if ( w->view()->model()->isLoading() ) + return true; - return w->selectPreviousMessageItem( messageTypeFilter, existingSelectionBehaviour, centerItem, loop ); - } else { - return false; - } + return w->selectPreviousMessageItem( messageTypeFilter, existingSelectionBehaviour, centerItem, loop ); + } else { + return false; + } } bool Pane::focusNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ) { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - if ( w->view()->model()->isLoading() ) - return true; + if ( w ) { + if ( w->view()->model()->isLoading() ) + return true; - return w->focusNextMessageItem( messageTypeFilter, centerItem, loop ); - } else { - return false; - } + return w->focusNextMessageItem( messageTypeFilter, centerItem, loop ); + } else { + return false; + } } bool Pane::focusPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ) { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - if ( w->view()->model()->isLoading() ) - return true; + if ( w ) { + if ( w->view()->model()->isLoading() ) + return true; - return w->focusPreviousMessageItem( messageTypeFilter, centerItem, loop ); - } else { - return false; - } + return w->focusPreviousMessageItem( messageTypeFilter, centerItem, loop ); + } else { + return false; + } } void Pane::selectFocusedMessageItem( bool centerItem ) { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - if ( w->view()->model()->isLoading() ) - return; + if ( w ) { + if ( w->view()->model()->isLoading() ) + return; - w->selectFocusedMessageItem( centerItem ); - } + w->selectFocusedMessageItem( centerItem ); + } } bool Pane::selectFirstMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem ) { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - if ( w->view()->model()->isLoading() ) - return true; + if ( w ) { + if ( w->view()->model()->isLoading() ) + return true; - return w->selectFirstMessageItem( messageTypeFilter, centerItem ); - } else { - return false; - } + return w->selectFirstMessageItem( messageTypeFilter, centerItem ); + } else { + return false; + } } bool Pane::selectLastMessageItem(Core::MessageTypeFilter messageTypeFilter, bool centerItem) { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - if ( w->view()->model()->isLoading() ) - return true; + if ( w ) { + if ( w->view()->model()->isLoading() ) + return true; - return w->selectLastMessageItem( messageTypeFilter, centerItem ); - } else { - return false; - } + return w->selectLastMessageItem( messageTypeFilter, centerItem ); + } else { + return false; + } } void Pane::selectAll() { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - if ( w->view()->model()->isLoading() ) - return; + if ( w ) { + if ( w->view()->model()->isLoading() ) + return; - w->selectAll(); - } + w->selectAll(); + } } void Pane::setCurrentThreadExpanded( bool expand ) { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - if ( w->view()->model()->isLoading() ) - return; + if ( w ) { + if ( w->view()->model()->isLoading() ) + return; - w->setCurrentThreadExpanded(expand ); - } + w->setCurrentThreadExpanded(expand ); + } } void Pane::setAllThreadsExpanded( bool expand ) { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - if ( w->view()->model()->isLoading() ) - return; + if ( w ) { + if ( w->view()->model()->isLoading() ) + return; - w->setAllThreadsExpanded( expand ); - } + w->setAllThreadsExpanded( expand ); + } } void Pane::setAllGroupsExpanded( bool expand ) { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - if ( w->view()->model()->isLoading() ) - return; + if ( w ) { + if ( w->view()->model()->isLoading() ) + return; - w->setAllGroupsExpanded(expand); - } + w->setAllGroupsExpanded(expand); + } } void Pane::focusQuickSearch() { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - w->focusQuickSearch(); - } + if ( w ) { + w->focusQuickSearch(); + } } void Pane::setQuickSearchClickMessage(const QString &msg) { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w ) { - w->setQuickSearchClickMessage(msg); - } + if ( w ) { + w->setQuickSearchClickMessage(msg); + } } void Pane::Private::onSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected ) { - if ( mPreferEmptyTab ) { - q->createNewTab(); - } + if ( mPreferEmptyTab ) { + q->createNewTab(); + } - Widget *w = static_cast( q->currentWidget() ); - QItemSelectionModel * s = mWidgetSelectionHash[w]; + Widget *w = static_cast( q->currentWidget() ); + QItemSelectionModel * s = mWidgetSelectionHash[w]; - w->saveCurrentSelection(); + w->saveCurrentSelection(); - // Deselect old before we select new - so that the messagelist can clear first. - s->select( mapSelectionToSource( deselected ), QItemSelectionModel::Deselect ); - if ( s->selection().isEmpty() ) { - w->view()->model()->setPreSelectionMode( mPreSelectionMode ); - } - s->select( mapSelectionToSource( selected ), QItemSelectionModel::Select ); - - QString label; - QIcon icon; - QString toolTip; - foreach ( const QModelIndex &index, s->selectedRows() ) { - label+= index.data( Qt::DisplayRole ).toString()+QLatin1String( ", " ); - } - label.chop( 2 ); - - if ( label.isEmpty() ) { - label = i18nc( "@title:tab Empty messagelist", "Empty" ); - icon = QIcon(); - } else if ( s->selectedRows().size()==1 ) { - icon = s->selectedRows().first().data( Qt::DecorationRole ).value(); - QModelIndex idx = s->selectedRows().first().parent(); - toolTip = label; - while ( idx != QModelIndex() ) { - toolTip = idx.data().toString() + QLatin1Char( '/' ) + toolTip; - idx = idx.parent(); - } - } else { - icon = KIcon( QLatin1String( "folder" ) ); - } - - const int index = q->indexOf( w ); - q->setTabText( index, label ); - q->setTabIcon( index, icon ); - q->setTabToolTip( index, toolTip); - if ( mPreferEmptyTab ) { - disconnect( mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - q, SLOT(onSelectionChanged(QItemSelection,QItemSelection)) ); + // Deselect old before we select new - so that the messagelist can clear first. + s->select( mapSelectionToSource( deselected ), QItemSelectionModel::Deselect ); + if ( s->selection().isEmpty() ) { + w->view()->model()->setPreSelectionMode( mPreSelectionMode ); + } + s->select( mapSelectionToSource( selected ), QItemSelectionModel::Select ); - mSelectionModel->select( mapSelectionFromSource( s->selection() ), - QItemSelectionModel::ClearAndSelect ); + QString label; + QIcon icon; + QString toolTip; + foreach ( const QModelIndex &index, s->selectedRows() ) { + label+= index.data( Qt::DisplayRole ).toString()+QLatin1String( ", " ); + } + label.chop( 2 ); - connect( mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - q, SLOT(onSelectionChanged(QItemSelection,QItemSelection)) ); + if ( label.isEmpty() ) { + label = i18nc( "@title:tab Empty messagelist", "Empty" ); + icon = QIcon(); + } else if ( s->selectedRows().size()==1 ) { + icon = s->selectedRows().first().data( Qt::DecorationRole ).value(); + QModelIndex idx = s->selectedRows().first().parent(); + toolTip = label; + while ( idx != QModelIndex() ) { + toolTip = idx.data().toString() + QLatin1Char( '/' ) + toolTip; + idx = idx.parent(); + } + } else { + icon = KIcon( QLatin1String( "folder" ) ); + } - } + const int index = q->indexOf( w ); + q->setTabText( index, label ); + q->setTabIcon( index, icon ); + q->setTabToolTip( index, toolTip); + if ( mPreferEmptyTab ) { + disconnect( mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + q, SLOT(onSelectionChanged(QItemSelection,QItemSelection)) ); + + mSelectionModel->select( mapSelectionFromSource( s->selection() ), + QItemSelectionModel::ClearAndSelect ); + + connect( mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + q, SLOT(onSelectionChanged(QItemSelection,QItemSelection)) ); + + } } void Pane::Private::activateTab() { - q->tabBar()->setCurrentIndex( q->sender()->objectName().right( 2 ).toInt() -1 ); + q->tabBar()->setCurrentIndex( q->sender()->objectName().right( 2 ).toInt() -1 ); } void Pane::Private::moveTabRight() { - const int numberOfTab = q->tabBar()->count(); - if( numberOfTab == 1 ) - return; - if ( QApplication::isRightToLeft() ) - moveTabForward(); - else - moveTabBackward(); + const int numberOfTab = q->tabBar()->count(); + if( numberOfTab == 1 ) + return; + if ( QApplication::isRightToLeft() ) + moveTabForward(); + else + moveTabBackward(); } void Pane::Private::moveTabLeft() { - const int numberOfTab = q->tabBar()->count(); - if( numberOfTab == 1 ) - return; - if ( QApplication::isRightToLeft() ) - moveTabBackward(); - else - moveTabForward(); + const int numberOfTab = q->tabBar()->count(); + if( numberOfTab == 1 ) + return; + if ( QApplication::isRightToLeft() ) + moveTabBackward(); + else + moveTabForward(); } void Pane::Private::moveTabForward() { - const int currentIndex = q->tabBar()->currentIndex(); - if ( currentIndex == q->tabBar()->count()-1 ) - return; - q->tabBar()->moveTab( currentIndex, currentIndex+1 ); + const int currentIndex = q->tabBar()->currentIndex(); + if ( currentIndex == q->tabBar()->count()-1 ) + return; + q->tabBar()->moveTab( currentIndex, currentIndex+1 ); } void Pane::Private::moveTabBackward() { - const int currentIndex = q->tabBar()->currentIndex(); - if ( currentIndex == 0 ) - return; - q->tabBar()->moveTab( currentIndex, currentIndex-1 ); + const int currentIndex = q->tabBar()->currentIndex(); + if ( currentIndex == 0 ) + return; + q->tabBar()->moveTab( currentIndex, currentIndex-1 ); } void Pane::Private::activateNextTab() { - const int numberOfTab = q->tabBar()->count(); - if( numberOfTab == 1 ) - return; + const int numberOfTab = q->tabBar()->count(); + if( numberOfTab == 1 ) + return; - int indexTab = ( q->tabBar()->currentIndex() + 1 ); + int indexTab = ( q->tabBar()->currentIndex() + 1 ); - if( indexTab == numberOfTab ) - indexTab = 0; + if( indexTab == numberOfTab ) + indexTab = 0; - q->tabBar()->setCurrentIndex( indexTab ); + q->tabBar()->setCurrentIndex( indexTab ); } void Pane::Private::activatePreviousTab() { - const int numberOfTab = q->tabBar()->count(); - if( numberOfTab == 1 ) - return; + const int numberOfTab = q->tabBar()->count(); + if( numberOfTab == 1 ) + return; - int indexTab = ( q->tabBar()->currentIndex() - 1 ); + int indexTab = ( q->tabBar()->currentIndex() - 1 ); - if( indexTab == -1 ) - indexTab = numberOfTab - 1; + if( indexTab == -1 ) + indexTab = numberOfTab - 1; - q->tabBar()->setCurrentIndex( indexTab ); + q->tabBar()->setCurrentIndex( indexTab ); } void Pane::Private::onNewTabClicked() { - q->createNewTab(); + q->createNewTab(); } void Pane::Private::onCloseTabClicked() { - closeTab( q->currentWidget() ); + closeTab( q->currentWidget() ); } void Pane::Private::closeTab( QWidget *w ) { - if ( !w || (q->count() < 2) ) { - return; - } + if ( !w || (q->count() < 2) ) { + return; + } - delete w; - updateTabControls(); + delete w; + updateTabControls(); } void Pane::Private::changeQuicksearchVisibility(bool show) { for ( int i=0; icount(); ++i ) { - Widget *w = qobject_cast( q->widget( i ) ); - w->changeQuicksearchVisibility(show); + Widget *w = qobject_cast( q->widget( i ) ); + w->changeQuicksearchVisibility(show); } } bool Pane::eventFilter( QObject *object, QEvent *event ) { - if ( event->type() == QEvent::MouseButtonPress ) { - QMouseEvent * const mouseEvent = static_cast( event ); - if ( mouseEvent->button() == Qt::MidButton ) { - return true; + if ( event->type() == QEvent::MouseButtonPress ) { + QMouseEvent * const mouseEvent = static_cast( event ); + if ( mouseEvent->button() == Qt::MidButton ) { + return true; + } } - } - return KTabWidget::eventFilter( object, event ); + return KTabWidget::eventFilter( object, event ); } void Pane::Private::onCurrentTabChanged() { - emit q->currentTabChanged(); + emit q->currentTabChanged(); - Widget *w = static_cast( q->currentWidget() ); + Widget *w = static_cast( q->currentWidget() ); - QItemSelectionModel *s = mWidgetSelectionHash[w]; + QItemSelectionModel *s = mWidgetSelectionHash[w]; - disconnect( mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - q, SLOT(onSelectionChanged(QItemSelection,QItemSelection)) ); + disconnect( mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + q, SLOT(onSelectionChanged(QItemSelection,QItemSelection)) ); - mSelectionModel->select( mapSelectionFromSource( s->selection() ), - QItemSelectionModel::ClearAndSelect ); + mSelectionModel->select( mapSelectionFromSource( s->selection() ), + QItemSelectionModel::ClearAndSelect ); - connect( mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - q, SLOT(onSelectionChanged(QItemSelection,QItemSelection)) ); + connect( mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + q, SLOT(onSelectionChanged(QItemSelection,QItemSelection)) ); } void Pane::Private::onTabContextMenuRequest( const QPoint &pos ) { - QTabBar *bar = q->tabBar(); - if ( q->count() <= 1 ) return; + QTabBar *bar = q->tabBar(); + if ( q->count() <= 1 ) return; - const int indexBar = bar->tabAt( bar->mapFrom( q, pos ) ); - if ( indexBar == -1 ) return; + const int indexBar = bar->tabAt( bar->mapFrom( q, pos ) ); + if ( indexBar == -1 ) return; - Widget *w = qobject_cast( q->widget( indexBar ) ); - if ( !w ) return; + Widget *w = qobject_cast( q->widget( indexBar ) ); + if ( !w ) return; - KMenu menu( q ); + KMenu menu( q ); - QAction *closeTabAction = menu.addAction( i18nc( "@action:inmenu", "Close Tab" ) ); - closeTabAction->setIcon( KIcon( QLatin1String( "tab-close" ) ) ); + QAction *closeTabAction = menu.addAction( i18nc( "@action:inmenu", "Close Tab" ) ); + closeTabAction->setIcon( KIcon( QLatin1String( "tab-close" ) ) ); - QAction *allOther = menu.addAction( i18nc("@action:inmenu", "Close All Other Tabs" ) ); - allOther->setIcon( KIcon( QLatin1String( "tab-close-other" ) ) ); + QAction *allOther = menu.addAction( i18nc("@action:inmenu", "Close All Other Tabs" ) ); + allOther->setIcon( KIcon( QLatin1String( "tab-close-other" ) ) ); - QAction *action = menu.exec( q->mapToGlobal( pos ) ); + QAction *action = menu.exec( q->mapToGlobal( pos ) ); - if ( action == allOther ) { // Close all other tabs - QList widgets; - const int index = q->indexOf( w ); + if ( action == allOther ) { // Close all other tabs + QList widgets; + const int index = q->indexOf( w ); - for ( int i=0; icount(); ++i ) { - if ( i==index) continue; // Skip the current one + for ( int i=0; icount(); ++i ) { + if ( i==index) continue; // Skip the current one - Widget *other = qobject_cast( q->widget( i ) ); - widgets << other; - } + Widget *other = qobject_cast( q->widget( i ) ); + widgets << other; + } - foreach ( Widget *other, widgets ) { - delete other; - } + foreach ( Widget *other, widgets ) { + delete other; + } - updateTabControls(); - } else if (action == closeTabAction) { - closeTab(q->widget(indexBar)); - } + updateTabControls(); + } else if (action == closeTabAction) { + closeTab(q->widget(indexBar)); + } } MessageList::StorageModel *Pane::createStorageModel( QAbstractItemModel *model, QItemSelectionModel *selectionModel, QObject *parent ) { - return new MessageList::StorageModel( model, selectionModel, parent ); + return new MessageList::StorageModel( model, selectionModel, parent ); } void Pane::setCurrentFolder( const Akonadi::Collection &collection, bool, Core::PreSelectionMode preSelectionMode, const QString &overrideLabel ) { - d->mPreSelectionMode = preSelectionMode; - Widget *w = static_cast( currentWidget() ); - if ( w ) { - w->setCurrentFolder( collection ); - QItemSelectionModel *s = d->mWidgetSelectionHash[w]; - MessageList::StorageModel *m = createStorageModel( d->mModel, s, w ); - w->setStorageModel( m, preSelectionMode ); - if ( !overrideLabel.isEmpty() ) { - int index = indexOf( w ); - setTabText( index, overrideLabel ); + d->mPreSelectionMode = preSelectionMode; + Widget *w = static_cast( currentWidget() ); + if ( w ) { + w->setCurrentFolder( collection ); + QItemSelectionModel *s = d->mWidgetSelectionHash[w]; + MessageList::StorageModel *m = createStorageModel( d->mModel, s, w ); + w->setStorageModel( m, preSelectionMode ); + if ( !overrideLabel.isEmpty() ) { + int index = indexOf( w ); + setTabText( index, overrideLabel ); + } } - } } void Pane::updateTabIconText( const Akonadi::Collection &collection, const QString&label, const QIcon& icon ) { - for ( int i=0; i( widget( i ) ); - if ( w->currentCollection() == collection ) - { - const int index = indexOf( w ); - setTabText( index, label ); - setTabIcon( index, icon ); + for ( int i=0; i( widget( i ) ); + if ( w->currentCollection() == collection ) + { + const int index = indexOf( w ); + setTabText( index, label ); + setTabIcon( index, icon ); + } } - } } QItemSelectionModel *Pane::createNewTab() { - Widget * w = new Widget( this ); - w->setXmlGuiClient( d->mXmlGuiClient ); + Widget * w = new Widget( this ); + w->setXmlGuiClient( d->mXmlGuiClient ); + + addTab( w, i18nc( "@title:tab Empty messagelist", "Empty" ) ); + + if(d->mXmlGuiClient && count() < 10) { + if(d->mMaxTabCreated < count() ) { + d->mMaxTabCreated = count(); + d->addActivateTabAction(d->mMaxTabCreated); + } + } + + QItemSelectionModel *s = new QItemSelectionModel( d->mModel, w ); + MessageList::StorageModel *m = createStorageModel( d->mModel, s, w ); + w->setStorageModel( m ); - addTab( w, i18nc( "@title:tab Empty messagelist", "Empty" ) ); + d->mWidgetSelectionHash[w] = s; - if(d->mXmlGuiClient && count() < 10) { - if(d->mMaxTabCreated < count() ) { - d->mMaxTabCreated = count(); - d->addActivateTabAction(d->mMaxTabCreated); - } - } - - QItemSelectionModel *s = new QItemSelectionModel( d->mModel, w ); - MessageList::StorageModel *m = createStorageModel( d->mModel, s, w ); - w->setStorageModel( m ); - - d->mWidgetSelectionHash[w] = s; - - connect( w, SIGNAL(messageSelected(Akonadi::Item)), - this, SIGNAL(messageSelected(Akonadi::Item)) ); - connect( w, SIGNAL(messageActivated(Akonadi::Item)), - this, SIGNAL(messageActivated(Akonadi::Item)) ); - connect( w, SIGNAL(selectionChanged()), - this, SIGNAL(selectionChanged()) ); - connect( w, SIGNAL(messageStatusChangeRequest(Akonadi::Item,Akonadi::MessageStatus,Akonadi::MessageStatus)), - this, SIGNAL(messageStatusChangeRequest(Akonadi::Item,Akonadi::MessageStatus,Akonadi::MessageStatus)) ); - - connect( w, SIGNAL(statusMessage(QString)), - this, SIGNAL(statusMessage(QString)) ); - - d->updateTabControls(); - setCurrentWidget( w ); - return s; + connect( w, SIGNAL(messageSelected(Akonadi::Item)), + this, SIGNAL(messageSelected(Akonadi::Item)) ); + connect( w, SIGNAL(messageActivated(Akonadi::Item)), + this, SIGNAL(messageActivated(Akonadi::Item)) ); + connect( w, SIGNAL(selectionChanged()), + this, SIGNAL(selectionChanged()) ); + connect( w, SIGNAL(messageStatusChangeRequest(Akonadi::Item,Akonadi::MessageStatus,Akonadi::MessageStatus)), + this, SIGNAL(messageStatusChangeRequest(Akonadi::Item,Akonadi::MessageStatus,Akonadi::MessageStatus)) ); + + connect( w, SIGNAL(statusMessage(QString)), + this, SIGNAL(statusMessage(QString)) ); + + d->updateTabControls(); + setCurrentWidget( w ); + return s; } QItemSelection Pane::Private::mapSelectionToSource( const QItemSelection &selection ) const { - QItemSelection result = selection; + QItemSelection result = selection; - foreach ( const QAbstractProxyModel *proxy, mProxyStack ) { - result = proxy->mapSelectionToSource( result ); - } + foreach ( const QAbstractProxyModel *proxy, mProxyStack ) { + result = proxy->mapSelectionToSource( result ); + } - return result; + return result; } QItemSelection Pane::Private::mapSelectionFromSource( const QItemSelection &selection ) const { - QItemSelection result = selection; + QItemSelection result = selection; - typedef QList::ConstIterator Iterator; + typedef QList::ConstIterator Iterator; - for ( Iterator it = mProxyStack.end()-1; it!=mProxyStack.begin(); --it ) { - result = (*it)->mapSelectionFromSource( result ); - } - result = mProxyStack.first()->mapSelectionFromSource( result ); + for ( Iterator it = mProxyStack.end()-1; it!=mProxyStack.begin(); --it ) { + result = (*it)->mapSelectionFromSource( result ); + } + result = mProxyStack.first()->mapSelectionFromSource( result ); - return result; + return result; } void Pane::Private::updateTabControls() { - const bool enableAction = ( q->count()>1 ); - if (mCloseTabButton) - mCloseTabButton->setEnabled( enableAction ); - if ( mCloseTabAction ) - mCloseTabAction->setEnabled( enableAction ); - if ( mActivatePreviousTabAction ) - mActivatePreviousTabAction->setEnabled( enableAction ); - if ( mActivateNextTabAction ) - mActivateNextTabAction->setEnabled( enableAction ); - if ( mMoveTabRightAction ) - mMoveTabRightAction->setEnabled( enableAction ); - if ( mMoveTabLeftAction ) - mMoveTabLeftAction->setEnabled( enableAction ); - - if ( Core::Settings::self()->autoHideTabBarWithSingleTab() ) { - q->tabBar()->setVisible( enableAction ); - } else { - q->tabBar()->setVisible( true ); - } - - const bool hasCloseButton(Core::Settings::self()->tabsHaveCloseButton()); - q->setTabsClosable( hasCloseButton ); - if( hasCloseButton ) { - const int numberOfTab(q->count()); - if( numberOfTab ==1) { - q->tabBar()->tabButton(0, QTabBar::RightSide)->setEnabled(false); - } else if(numberOfTab > 1) { - q->tabBar()->tabButton(0, QTabBar::RightSide)->setEnabled(true); + const bool enableAction = ( q->count()>1 ); + if (mCloseTabButton) + mCloseTabButton->setEnabled( enableAction ); + if ( mCloseTabAction ) + mCloseTabAction->setEnabled( enableAction ); + if ( mActivatePreviousTabAction ) + mActivatePreviousTabAction->setEnabled( enableAction ); + if ( mActivateNextTabAction ) + mActivateNextTabAction->setEnabled( enableAction ); + if ( mMoveTabRightAction ) + mMoveTabRightAction->setEnabled( enableAction ); + if ( mMoveTabLeftAction ) + mMoveTabLeftAction->setEnabled( enableAction ); + + if ( Core::Settings::self()->autoHideTabBarWithSingleTab() ) { + q->tabBar()->setVisible( enableAction ); + } else { + q->tabBar()->setVisible( true ); + } + + const bool hasCloseButton(Core::Settings::self()->tabsHaveCloseButton()); + q->setTabsClosable( hasCloseButton ); + if( hasCloseButton ) { + const int numberOfTab(q->count()); + if( numberOfTab ==1) { + q->tabBar()->tabButton(0, QTabBar::RightSide)->setEnabled(false); + } else if(numberOfTab > 1) { + q->tabBar()->tabButton(0, QTabBar::RightSide)->setEnabled(true); + } } - } } Item Pane::currentItem() const { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w == 0 ) { - return Item(); - } + if ( w == 0 ) { + return Item(); + } - return w->currentItem(); + return w->currentItem(); } KMime::Message::Ptr Pane::currentMessage() const { - Widget *w = static_cast( currentWidget() ); + Widget *w = static_cast( currentWidget() ); - if ( w == 0 ) { - return KMime::Message::Ptr(); - } + if ( w == 0 ) { + return KMime::Message::Ptr(); + } - return w->currentMessage(); + return w->currentMessage(); } QList Pane::selectionAsMessageList( bool includeCollapsedChildren ) const { - Widget *w = static_cast( currentWidget() ); - if ( w == 0 ) { - return QList(); - } - return w->selectionAsMessageList( includeCollapsedChildren ); + Widget *w = static_cast( currentWidget() ); + if ( w == 0 ) { + return QList(); + } + return w->selectionAsMessageList( includeCollapsedChildren ); } QList Pane::selectionAsMessageItemList( bool includeCollapsedChildren ) const { - Widget *w = static_cast( currentWidget() ); - if ( w == 0 ) { - return QList(); - } - return w->selectionAsMessageItemList( includeCollapsedChildren ); + Widget *w = static_cast( currentWidget() ); + if ( w == 0 ) { + return QList(); + } + return w->selectionAsMessageItemList( includeCollapsedChildren ); } QList Pane::selectionAsListMessageId( bool includeCollapsedChildren ) const { - Widget *w = static_cast( currentWidget() ); - if ( w == 0 ) { - return QList(); - } - return w->selectionAsListMessageId( includeCollapsedChildren ); + Widget *w = static_cast( currentWidget() ); + if ( w == 0 ) { + return QList(); + } + return w->selectionAsListMessageId( includeCollapsedChildren ); } QVector Pane::selectionAsMessageItemListId( bool includeCollapsedChildren ) const { - Widget *w = static_cast( currentWidget() ); - if ( w == 0 ) { - return QVector(); - } - return w->selectionAsMessageItemListId( includeCollapsedChildren ); + Widget *w = static_cast( currentWidget() ); + if ( w == 0 ) { + return QVector(); + } + return w->selectionAsMessageItemListId( includeCollapsedChildren ); } QList Pane::currentThreadAsMessageList() const { - Widget *w = static_cast( currentWidget() ); - if ( w == 0 ) { - return QList(); - } - return w->currentThreadAsMessageList(); + Widget *w = static_cast( currentWidget() ); + if ( w == 0 ) { + return QList(); + } + return w->currentThreadAsMessageList(); } QList Pane::itemListFromPersistentSet( MessageList::Core::MessageItemSetReference ref ) { - Widget *w = static_cast( currentWidget() ); - if ( w ) { - return w->itemListFromPersistentSet(ref); - } - return QList(); + Widget *w = static_cast( currentWidget() ); + if ( w ) { + return w->itemListFromPersistentSet(ref); + } + return QList(); } void Pane::deletePersistentSet( MessageList::Core::MessageItemSetReference ref ) { - Widget *w = static_cast( currentWidget() ); - if ( w ) { - w->deletePersistentSet( ref ); - } + Widget *w = static_cast( currentWidget() ); + if ( w ) { + w->deletePersistentSet( ref ); + } } void Pane::markMessageItemsAsAboutToBeRemoved( MessageList::Core::MessageItemSetReference ref, bool bMark ) { - Widget *w = static_cast( currentWidget() ); - if ( w ) { - w->markMessageItemsAsAboutToBeRemoved( ref, bMark ); - } + Widget *w = static_cast( currentWidget() ); + if ( w ) { + w->markMessageItemsAsAboutToBeRemoved( ref, bMark ); + } } QList Pane::currentFilterStatus() const { - Widget *w = static_cast( currentWidget() ); - if ( w == 0 ) { - return QList(); - } - return w->currentFilterStatus(); + Widget *w = static_cast( currentWidget() ); + if ( w == 0 ) { + return QList(); + } + return w->currentFilterStatus(); } QString Pane::currentFilterSearchString() const { - Widget *w = static_cast( currentWidget() ); - if ( w ) { - return w->currentFilterSearchString(); - } - return QString(); + Widget *w = static_cast( currentWidget() ); + if ( w ) { + return w->currentFilterSearchString(); + } + return QString(); } bool Pane::isThreaded() const { - Widget *w = static_cast( currentWidget() ); - if ( w ) { - return w->isThreaded(); - } - return false; + Widget *w = static_cast( currentWidget() ); + if ( w ) { + return w->isThreaded(); + } + return false; } bool Pane::selectionEmpty() const { - Widget *w = static_cast( currentWidget() ); - if ( w ) { - return w->selectionEmpty(); - } - return false; + Widget *w = static_cast( currentWidget() ); + if ( w ) { + return w->selectionEmpty(); + } + return false; } bool Pane::getSelectionStats( Akonadi::Item::List &selectedItems, @@ -946,183 +946,183 @@ bool * allSelectedBelongToSameThread, bool includeCollapsedChildren ) const { - Widget * w = static_cast( currentWidget() ); - if ( w == 0 ) { - return false; - } + Widget * w = static_cast( currentWidget() ); + if ( w == 0 ) { + return false; + } - return w->getSelectionStats( - selectedItems, selectedVisibleItems, - allSelectedBelongToSameThread, includeCollapsedChildren - ); + return w->getSelectionStats( + selectedItems, selectedVisibleItems, + allSelectedBelongToSameThread, includeCollapsedChildren + ); } MessageList::Core::MessageItemSetReference Pane::selectionAsPersistentSet( bool includeCollapsedChildren ) const { - Widget *w = static_cast( currentWidget() ); - if ( w ) - return w->selectionAsPersistentSet( includeCollapsedChildren ); - return -1; + Widget *w = static_cast( currentWidget() ); + if ( w ) + return w->selectionAsPersistentSet( includeCollapsedChildren ); + return -1; } MessageList::Core::MessageItemSetReference Pane::currentThreadAsPersistentSet() const { - Widget *w = static_cast( currentWidget() ); - if ( w ) - return w->currentThreadAsPersistentSet(); - return -1; + Widget *w = static_cast( currentWidget() ); + if ( w ) + return w->currentThreadAsPersistentSet(); + return -1; } void Pane::focusView() { - Widget *w = static_cast( currentWidget() ); - if ( w ) { - QWidget *view = w->view(); - if ( view ) - view->setFocus(); - } + Widget *w = static_cast( currentWidget() ); + if ( w ) { + QWidget *view = w->view(); + if ( view ) + view->setFocus(); + } } void Pane::reloadGlobalConfiguration() { - d->updateTabControls(); + d->updateTabControls(); } QItemSelectionModel* Pane::currentItemSelectionModel() { - Widget *w = static_cast( currentWidget() ); - if ( w ) - return w->view()->selectionModel(); - return 0; + Widget *w = static_cast( currentWidget() ); + if ( w ) + return w->view()->selectionModel(); + return 0; } void Pane::resetModelStorage() { - Widget *w = static_cast( currentWidget() ); - if ( w ) { - MessageList::StorageModel *m = static_cast( w->storageModel() ); - if ( m ) - m->resetModelStorage(); - } + Widget *w = static_cast( currentWidget() ); + if ( w ) { + MessageList::StorageModel *m = static_cast( w->storageModel() ); + if ( m ) + m->resetModelStorage(); + } } void Pane::setPreferEmptyTab( bool emptyTab ) { - d->mPreferEmptyTab = emptyTab; + d->mPreferEmptyTab = emptyTab; } void Pane::saveCurrentSelection() { - for ( int i=0; i( widget( i ) ); - w->saveCurrentSelection(); - } + for ( int i=0; i( widget( i ) ); + w->saveCurrentSelection(); + } } void Pane::updateTagComboBox() { - for ( int i=0; i( widget( i ) ); - w->populateStatusFilterCombo(); - } + for ( int i=0; i( widget( i ) ); + w->populateStatusFilterCombo(); + } } void Pane::writeConfig(bool restoreSession) { - KConfigGroup conf( MessageList::Core::Settings::self()->config(),"MessageListPane"); + KConfigGroup conf( MessageList::Core::Settings::self()->config(),"MessageListPane"); - // Delete list before - const QStringList list = MessageList::Core::Settings::self()->config()->groupList().filter( QRegExp( QLatin1String("MessageListTab\\d+") ) ); - foreach ( const QString &group, list ) { - MessageList::Core::Settings::self()->config()->deleteGroup( group ); - } - - if (restoreSession) { - conf.writeEntry(QLatin1String("currentIndex"),currentIndex()); - conf.writeEntry(QLatin1String("tabNumber"),count()); + // Delete list before + const QStringList list = MessageList::Core::Settings::self()->config()->groupList().filter( QRegExp( QLatin1String("MessageListTab\\d+") ) ); + foreach ( const QString &group, list ) { + MessageList::Core::Settings::self()->config()->deleteGroup( group ); + } - for ( int i=0; i( widget( i ) ); - KConfigGroup grp(MessageList::Core::Settings::self()->config(),QString::fromLatin1("MessageListTab%1").arg(i)); - grp.writeEntry(QLatin1String("collectionId"),w->currentCollection().id()); - grp.writeEntry(QLatin1String("HeaderState"), w->view()->header()->saveState()); + if (restoreSession) { + conf.writeEntry(QLatin1String("currentIndex"),currentIndex()); + conf.writeEntry(QLatin1String("tabNumber"),count()); + + for ( int i=0; i( widget( i ) ); + KConfigGroup grp(MessageList::Core::Settings::self()->config(),QString::fromLatin1("MessageListTab%1").arg(i)); + grp.writeEntry(QLatin1String("collectionId"),w->currentCollection().id()); + grp.writeEntry(QLatin1String("HeaderState"), w->view()->header()->saveState()); + } } - } - conf.sync(); + conf.sync(); } void Pane::readConfig(bool restoreSession) { - if(restoreSession && MessageList::Core::Settings::self()->config()->hasGroup(QLatin1String("MessageListPane"))) { - KConfigGroup conf( MessageList::Core::Settings::self()->config(),"MessageListPane"); - const int numberOfTab = conf.readEntry(QLatin1String("tabNumber"),0); - if(numberOfTab == 0) { - createNewTab(); - } else { - for(int i = 0; iconfig(),QString::fromLatin1("MessageListTab%1").arg(i)); - QItemSelectionModel *selectionModel = createNewTab(); + if(restoreSession && MessageList::Core::Settings::self()->config()->hasGroup(QLatin1String("MessageListPane"))) { + KConfigGroup conf( MessageList::Core::Settings::self()->config(),"MessageListPane"); + const int numberOfTab = conf.readEntry(QLatin1String("tabNumber"),0); + if(numberOfTab == 0) { + createNewTab(); + } else { + for(int i = 0; iconfig(),QString::fromLatin1("MessageListTab%1").arg(i)); + QItemSelectionModel *selectionModel = createNewTab(); #if 0 - Akonadi::Collection::Id id = grp.readEntry(QLatin1String("collectionId"),-1); - ETMViewStateSaver *saver = new ETMViewStateSaver; - saver->setSelectionModel(selectionModel); - - if(id != -1) { - ETMViewStateSaver *saver = new ETMViewStateSaver; - saver->setSelectionModel(selectionModel); - saver->restoreState( grp ); - saver->selectCollections(Akonadi::Collection::List()<restoreCurrentItem( QString::fromLatin1("c%1").arg(id) ); - } + Akonadi::Collection::Id id = grp.readEntry(QLatin1String("collectionId"),-1); + ETMViewStateSaver *saver = new ETMViewStateSaver; + saver->setSelectionModel(selectionModel); + + if(id != -1) { + ETMViewStateSaver *saver = new ETMViewStateSaver; + saver->setSelectionModel(selectionModel); + saver->restoreState( grp ); + saver->selectCollections(Akonadi::Collection::List()<restoreCurrentItem( QString::fromLatin1("c%1").arg(id) ); + } #else - Q_UNUSED( selectionModel ); + Q_UNUSED( selectionModel ); #endif - Widget *w = qobject_cast( widget( i ) ); - w->view()->header()->restoreState(grp.readEntry(QLatin1String("HeaderState"),QByteArray())); - } - setCurrentIndex(conf.readEntry(QLatin1String("currentIndex"),0)); - } - } else { - createNewTab(); - } + Widget *w = qobject_cast( widget( i ) ); + w->view()->header()->restoreState(grp.readEntry(QLatin1String("HeaderState"),QByteArray())); + } + setCurrentIndex(conf.readEntry(QLatin1String("currentIndex"),0)); + } + } else { + createNewTab(); + } } bool Pane::searchEditHasFocus() const { - Widget *w = static_cast( currentWidget() ); - if ( w ) - return w->searchEditHasFocus(); - return false; + Widget *w = static_cast( currentWidget() ); + if ( w ) + return w->searchEditHasFocus(); + return false; } void Pane::sortOrderMenuAboutToShow() { - KMenu * menu = dynamic_cast< KMenu * >( sender() ); - if ( !menu ) - return; - const Widget * const w = static_cast( currentWidget() ); - w->view()->sortOrderMenuAboutToShow(menu); + KMenu * menu = dynamic_cast< KMenu * >( sender() ); + if ( !menu ) + return; + const Widget * const w = static_cast( currentWidget() ); + w->view()->sortOrderMenuAboutToShow(menu); } void Pane::aggregationMenuAboutToShow() { - KMenu * menu = dynamic_cast< KMenu * >( sender() ); - if ( !menu ) - return; - const Widget * const w = static_cast( currentWidget() ); - w->view()->aggregationMenuAboutToShow(menu); + KMenu * menu = dynamic_cast< KMenu * >( sender() ); + if ( !menu ) + return; + const Widget * const w = static_cast( currentWidget() ); + w->view()->aggregationMenuAboutToShow(menu); } void Pane::themeMenuAboutToShow() { - KMenu * menu = dynamic_cast< KMenu * >( sender() ); - if ( !menu ) - return; - const Widget * const w = static_cast( currentWidget() ); - w->view()->themeMenuAboutToShow(menu); + KMenu * menu = dynamic_cast< KMenu * >( sender() ); + if ( !menu ) + return; + const Widget * const w = static_cast( currentWidget() ); + w->view()->themeMenuAboutToShow(menu); } diff -Nru kdepim-4.12.97/messagelist/pane.h kdepim-4.13.0/messagelist/pane.h --- kdepim-4.12.97/messagelist/pane.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/pane.h 2014-04-10 07:40:20.000000000 +0000 @@ -38,12 +38,12 @@ namespace KPIM { - class MessageStatus; +class MessageStatus; } namespace Akonadi { - class Item; +class Item; } namespace MessageList @@ -64,21 +64,21 @@ */ class MESSAGELIST_EXPORT Pane : public KTabWidget { - Q_OBJECT + Q_OBJECT public: - /** + /** * Create a Pane wrapping the specified model and selection. */ - explicit Pane(bool restoreSession, QAbstractItemModel *model, QItemSelectionModel *selectionModel, QWidget *parent = 0 ); - ~Pane(); + explicit Pane(bool restoreSession, QAbstractItemModel *model, QItemSelectionModel *selectionModel, QWidget *parent = 0 ); + ~Pane(); - virtual MessageList::StorageModel *createStorageModel( QAbstractItemModel *model, QItemSelectionModel *selectionModel, QObject *parent ); + virtual MessageList::StorageModel *createStorageModel( QAbstractItemModel *model, QItemSelectionModel *selectionModel, QObject *parent ); - virtual void writeConfig(bool restoreSession); + virtual void writeConfig(bool restoreSession); - /** + /** * Sets the XML GUI client which the pane is used in. * * This is needed if you want to use the built-in context menu. @@ -86,22 +86,22 @@ * * @param xmlGuiClient The KXMLGUIClient the view is used in. */ - void setXmlGuiClient( KXMLGUIClient *xmlGuiClient ); + void setXmlGuiClient( KXMLGUIClient *xmlGuiClient ); - /** + /** * Returns the current message for the list as Akonadi::Item. * May return an invalid Item if there is no current message or no current folder. */ - Akonadi::Item currentItem() const; + Akonadi::Item currentItem() const; - /** + /** * Returns the current message for the list as KMime::Message::Ptr. * May return 0 if there is no current message or no current folder. */ - KMime::Message::Ptr currentMessage() const; + KMime::Message::Ptr currentMessage() const; - /** + /** * Returns the currently selected KMime::Message::Ptr (bound to current StorageModel). * The list may be empty if there are no selected messages or no StorageModel. * @@ -112,9 +112,9 @@ * to the main even loop. Don't store it for any longer. If you need to reference * this set of messages at a later stage then take a look at createPersistentSet(). */ - QList selectionAsMessageList( bool includeCollapsedChildren = true ) const; + QList selectionAsMessageList( bool includeCollapsedChildren = true ) const; - /** + /** * Returns the currently selected Items (bound to current StorageModel). * The list may be empty if there are no selected messages or no StorageModel. * @@ -125,9 +125,9 @@ * to the main even loop. Don't store it for any longer. If you need to reference * this set of messages at a later stage then take a look at createPersistentSet(). */ - QList selectionAsMessageItemList( bool includeCollapsedChildren = true ) const; + QList selectionAsMessageItemList( bool includeCollapsedChildren = true ) const; - /** + /** * Returns the currently selected Items id(bound to current StorageModel). * The list may be empty if there are no selected messages or no StorageModel. * @@ -138,11 +138,11 @@ * to the main even loop. Don't store it for any longer. If you need to reference * this set of messages at a later stage then take a look at createPersistentSet(). */ - QVector selectionAsMessageItemListId( bool includeCollapsedChildren = true ) const; + QVector selectionAsMessageItemListId( bool includeCollapsedChildren = true ) const; - QList selectionAsListMessageId( bool includeCollapsedChildren = true) const; + QList selectionAsListMessageId( bool includeCollapsedChildren = true) const; - /** + /** * Returns the Akonadi::Item bound to the current StorageModel that * are part of the current thread. The current thread is the thread * that contains currentMessageItem(). @@ -152,10 +152,10 @@ * to the main even loop. Don't store it for any longer. If you need to reference * this set of messages at a later stage then take a look at createPersistentSet(). */ - QList currentThreadAsMessageList() const; + QList currentThreadAsMessageList() const; - /** + /** * Selects the next message item in the view. * * messageTypeFilter can be used to restrict the selection to only certain message types. @@ -168,12 +168,12 @@ * If loop is true then the "next" algorithm will restart from the beginning * of the list if the end is reached, otherwise it will just stop returning false. */ - bool selectNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, - MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, - bool centerItem, - bool loop ); + bool selectNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, + MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, + bool centerItem, + bool loop ); - /** + /** * Selects the previous message item in the view. * If centerItem is true then the specified item will be positioned * at the center of the view, if possible. @@ -186,12 +186,12 @@ * If loop is true then the "previous" algorithm will restart from the end * of the list if the beginning is reached, otherwise it will just stop returning false. */ - bool selectPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, - MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, - bool centerItem, - bool loop ); + bool selectPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, + MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, + bool centerItem, + bool loop ); - /** + /** * Focuses the next message item in the view without actually selecting it. * * messageTypeFilter can be used to restrict the selection to only certain message types. @@ -201,9 +201,9 @@ * If loop is true then the "next" algorithm will restart from the beginning * of the list if the end is reached, otherwise it will just stop returning false. */ - bool focusNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); + bool focusNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); - /** + /** * Focuses the previous message item in the view without actually selecting it. * * messageTypeFilter can be used to restrict the selection to only certain message types. @@ -213,17 +213,17 @@ * If loop is true then the "previous" algorithm will restart from the end * of the list if the beginning is reached, otherwise it will just stop returning false. */ - bool focusPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); + bool focusPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); - /** + /** * Selects the currently focused message item. May do nothing if the * focused message item is already selected (which is very likely). * If centerItem is true then the specified item will be positioned * at the center of the view, if possible. */ - void selectFocusedMessageItem( bool centerItem ); + void selectFocusedMessageItem( bool centerItem ); - /** + /** * Selects the first message item in the view that matches the specified Core::MessageTypeFilter. * If centerItem is true then the specified item will be positioned * at the center of the view, if possible. @@ -238,64 +238,64 @@ * * The function returns true if a message was selected and false otherwise. */ - bool selectFirstMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem ); + bool selectFirstMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem ); - /** + /** * Selects the last message item in the view that matches the specified Core::MessageTypeFilter. * If centerItem is true then the specified item will be positioned * at the center of the view, if possible. * * The function returns true if a message was selected and false otherwise. */ - bool selectLastMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem ); + bool selectLastMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem ); - /** + /** * If expand is true then it expands the current thread, otherwise * collapses it. */ - void setCurrentThreadExpanded( bool expand ); + void setCurrentThreadExpanded( bool expand ); - /** + /** * If expand is true then it expands all the threads, otherwise * collapses them. */ - void setAllThreadsExpanded( bool expand ); + void setAllThreadsExpanded( bool expand ); - /** + /** * If expand is true then it expands all the groups (only the toplevel * group item: inner threads are NOT expanded). If expand is false * then it collapses all the groups. If no grouping is in effect * then this function does nothing. */ - void setAllGroupsExpanded( bool expand ); + void setAllGroupsExpanded( bool expand ); - /** + /** * Sets the focus on the quick search line of the currently active tab. */ - void focusQuickSearch(); + void focusQuickSearch(); - /** + /** * Returns the Akonadi::MessageStatus in the current quicksearch field. */ - QList currentFilterStatus() const; + QList currentFilterStatus() const; - /** + /** * Returns the search term in the current quicksearch field. */ - QString currentFilterSearchString() const; + QString currentFilterSearchString() const; - /** + /** * Returns true if the current Aggregation is threaded, false otherwise * (or if there is no current Aggregation). */ - bool isThreaded() const; + bool isThreaded() const; - /** + /** * Fast function that determines if the selection is empty */ - bool selectionEmpty() const; - /** + bool selectionEmpty() const; + /** * Fills the lists of the selected message serial numbers and of the selected+visible ones. * Returns true if the returned stats are valid (there is a current folder after all) * and false otherwise. This is called by KMMainWidget in a single place so we optimize by @@ -304,56 +304,56 @@ * If includeCollapsedChildren is true then the children of the selected but * collapsed items are also included in the stats */ - bool getSelectionStats( Akonadi::Item::List &selectedItems, - Akonadi::Item::List &selectedVisibleItems, - bool * allSelectedBelongToSameThread, - bool includeCollapsedChildren = true) const; - /** + bool getSelectionStats( Akonadi::Item::List &selectedItems, + Akonadi::Item::List &selectedVisibleItems, + bool * allSelectedBelongToSameThread, + bool includeCollapsedChildren = true) const; + /** * Deletes the persistent set pointed by the specified reference. * If the set does not exist anymore, nothing happens. */ - void deletePersistentSet( MessageList::Core::MessageItemSetReference ref ); + void deletePersistentSet( MessageList::Core::MessageItemSetReference ref ); - /** + /** * If bMark is true this function marks the messages as "about to be removed" * so they appear dimmer and aren't selectable in the view. * If bMark is false then this function clears the "about to be removed" state * for the specified MessageItems. */ - void markMessageItemsAsAboutToBeRemoved( MessageList::Core::MessageItemSetReference ref, bool bMark ); + void markMessageItemsAsAboutToBeRemoved( MessageList::Core::MessageItemSetReference ref, bool bMark ); - /** + /** * Return Akonadi::Item from messageItemReference */ - QList itemListFromPersistentSet( MessageList::Core::MessageItemSetReference ref ); + QList itemListFromPersistentSet( MessageList::Core::MessageItemSetReference ref ); - /** + /** * Return a persistent set from current selection */ - MessageList::Core::MessageItemSetReference selectionAsPersistentSet( bool includeCollapsedChildren = true ) const; + MessageList::Core::MessageItemSetReference selectionAsPersistentSet( bool includeCollapsedChildren = true ) const; - /** + /** * Return a persistent set from current thread */ - MessageList::Core::MessageItemSetReference currentThreadAsPersistentSet() const; - /** + MessageList::Core::MessageItemSetReference currentThreadAsPersistentSet() const; + /** * Sets the focus on the view of the currently active tab. */ - void focusView(); + void focusView(); - /** + /** * Reloads global configuration and eventually reloads all the views. */ - void reloadGlobalConfiguration(); + void reloadGlobalConfiguration(); - /** + /** * Returns the QItemSelectionModel for the currently displayed tab. */ - QItemSelectionModel* currentItemSelectionModel(); + QItemSelectionModel* currentItemSelectionModel(); - /** + /** * Sets the current folder to be displayed by this Pane. * If the specified folder is already open in one of the tabs * then that tab is made current (and no reloading happens). @@ -371,47 +371,47 @@ * specified folder. This is useful to signal a particular folder state * like "loading..." */ - void setCurrentFolder( - const Akonadi::Collection &fld, - bool preferEmptyTab = false, - MessageList::Core::PreSelectionMode preSelectionMode = MessageList::Core::PreSelectLastSelected, - const QString &overrideLabel = QString() - ); + void setCurrentFolder( + const Akonadi::Collection &fld, + bool preferEmptyTab = false, + MessageList::Core::PreSelectionMode preSelectionMode = MessageList::Core::PreSelectLastSelected, + const QString &overrideLabel = QString() + ); - void resetModelStorage(); + void resetModelStorage(); - void setPreferEmptyTab( bool emptyTab ); + void setPreferEmptyTab( bool emptyTab ); - void updateTabIconText( const Akonadi::Collection &collection, const QString&label, const QIcon& icon ); + void updateTabIconText( const Akonadi::Collection &collection, const QString&label, const QIcon& icon ); - void saveCurrentSelection(); + void saveCurrentSelection(); - void updateTagComboBox(); + void updateTagComboBox(); - bool searchEditHasFocus() const; + bool searchEditHasFocus() const; - void setQuickSearchClickMessage(const QString &msg); + void setQuickSearchClickMessage(const QString &msg); public slots: - /** + /** * Selects all the items in the current folder. */ - void selectAll(); + void selectAll(); - /** + /** * Add a new tab to the Pane and select it. */ - QItemSelectionModel *createNewTab(); + QItemSelectionModel *createNewTab(); - void sortOrderMenuAboutToShow(); + void sortOrderMenuAboutToShow(); - void aggregationMenuAboutToShow(); + void aggregationMenuAboutToShow(); - void themeMenuAboutToShow(); + void themeMenuAboutToShow(); signals: - /** + /** * Emitted when a message is selected (that is, single clicked and thus made current in the view) * Note that this message CAN be 0 (when the current item is cleared, for example). * @@ -421,61 +421,61 @@ * this signal only for the last clicked message (or at all, if the last shift+clicked * thing is a group header...). You should handle selection changed in this case. */ - void messageSelected( const Akonadi::Item &item ); + void messageSelected( const Akonadi::Item &item ); - /** + /** * Emitted when a message is doubleclicked or activated by other input means */ - void messageActivated( const Akonadi::Item &item ); + void messageActivated( const Akonadi::Item &item ); - /** + /** * Emitted when the selection in the view changes. */ - void selectionChanged(); + void selectionChanged(); - /** + /** * Emitted when a message wants its status to be changed */ - void messageStatusChangeRequest( const Akonadi::Item &item, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear ); + void messageStatusChangeRequest( const Akonadi::Item &item, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear ); - /** + /** * Notify the outside when updating the status bar with a message * could be useful */ - void statusMessage( const QString &message ); + void statusMessage( const QString &message ); - /** + /** * Emitted when the current tab has changed. Clients using the * selection model from currentItemSelectionModel() should * ask for it again, as it may be different now. */ - void currentTabChanged(); + void currentTabChanged(); private: - void readConfig(bool restoreSession); + void readConfig(bool restoreSession); - Q_PRIVATE_SLOT(d, void onSelectionChanged( const QItemSelection&, const QItemSelection& )) - Q_PRIVATE_SLOT(d, void onNewTabClicked()) - Q_PRIVATE_SLOT(d, void onCloseTabClicked()) - Q_PRIVATE_SLOT(d, void activateTab()) - Q_PRIVATE_SLOT(d, void moveTabLeft()) - Q_PRIVATE_SLOT(d, void moveTabRight()) - Q_PRIVATE_SLOT(d, void activateNextTab()) - Q_PRIVATE_SLOT(d, void activatePreviousTab()) - Q_PRIVATE_SLOT(d, void closeTab( QWidget * )) - Q_PRIVATE_SLOT(d, void onCurrentTabChanged()) - Q_PRIVATE_SLOT(d, void onTabContextMenuRequest( const QPoint& )) - Q_PRIVATE_SLOT(d, void updateTabControls()) - Q_PRIVATE_SLOT(d, void changeQuicksearchVisibility(bool)) + Q_PRIVATE_SLOT(d, void onSelectionChanged( const QItemSelection&, const QItemSelection& )) + Q_PRIVATE_SLOT(d, void onNewTabClicked()) + Q_PRIVATE_SLOT(d, void onCloseTabClicked()) + Q_PRIVATE_SLOT(d, void activateTab()) + Q_PRIVATE_SLOT(d, void moveTabLeft()) + Q_PRIVATE_SLOT(d, void moveTabRight()) + Q_PRIVATE_SLOT(d, void activateNextTab()) + Q_PRIVATE_SLOT(d, void activatePreviousTab()) + Q_PRIVATE_SLOT(d, void closeTab( QWidget * )) + Q_PRIVATE_SLOT(d, void onCurrentTabChanged()) + Q_PRIVATE_SLOT(d, void onTabContextMenuRequest( const QPoint& )) + Q_PRIVATE_SLOT(d, void updateTabControls()) + Q_PRIVATE_SLOT(d, void changeQuicksearchVisibility(bool)) - bool eventFilter( QObject *obj, QEvent *event ); + bool eventFilter( QObject *obj, QEvent *event ); - class Private; - Private * const d; + class Private; + Private * const d; }; } // namespace MessageList diff -Nru kdepim-4.12.97/messagelist/storagemodel.cpp kdepim-4.13.0/messagelist/storagemodel.cpp --- kdepim-4.12.97/messagelist/storagemodel.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/storagemodel.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -51,20 +51,20 @@ class StorageModel::Private { public: - void onSourceDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight ); - void onSelectionChanged(); - void loadSettings(); - - StorageModel * const q; - - QAbstractItemModel *mModel; - QItemSelectionModel *mSelectionModel; - - Private( StorageModel *owner ) - : q( owner ), - mModel(0), - mSelectionModel(0) - {} + void onSourceDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight ); + void onSelectionChanged(); + void loadSettings(); + + StorageModel * const q; + + QAbstractItemModel *mModel; + QItemSelectionModel *mSelectionModel; + + Private( StorageModel *owner ) + : q( owner ), + mModel(0), + mSelectionModel(0) + {} }; } // namespace MessageList @@ -76,11 +76,11 @@ KMime::Message::Ptr messageForItem( const Akonadi::Item &item ) { - if ( !item.hasPayload() ) { - kWarning() << "Not a message" << item.id() << item.remoteId() << item.mimeType(); - return KMime::Message::Ptr(); - } - return item.payload(); + if ( !item.hasPayload() ) { + kWarning() << "Not a message" << item.id() << item.remoteId() << item.mimeType(); + return KMime::Message::Ptr(); + } + return item.payload(); } } @@ -88,314 +88,314 @@ static QAtomicInt _k_attributeInitialized; StorageModel::StorageModel( QAbstractItemModel *model, QItemSelectionModel *selectionModel, QObject *parent ) - : Core::StorageModel( parent ), d( new Private( this ) ) + : Core::StorageModel( parent ), d( new Private( this ) ) { - d->mSelectionModel = selectionModel; - if ( _k_attributeInitialized.testAndSetAcquire( 0, 1 ) ) { - AttributeFactory::registerAttribute(); - } - - Akonadi::SelectionProxyModel *childrenFilter = new Akonadi::SelectionProxyModel( d->mSelectionModel, this ); - childrenFilter->setSourceModel( model ); - childrenFilter->setFilterBehavior( KSelectionProxyModel::ChildrenOfExactSelection ); - - EntityMimeTypeFilterModel *itemFilter = new EntityMimeTypeFilterModel( this ); - itemFilter->setSourceModel( childrenFilter ); - itemFilter->addMimeTypeExclusionFilter( Collection::mimeType() ); - itemFilter->addMimeTypeInclusionFilter( QLatin1String( "message/rfc822" ) ); - itemFilter->setHeaderGroup( EntityTreeModel::ItemListHeaders ); - - d->mModel = itemFilter; - - kDebug() << "Using model:" << model->metaObject()->className(); - - connect( d->mModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(onSourceDataChanged(QModelIndex,QModelIndex)) ); - - connect( d->mModel, SIGNAL(layoutAboutToBeChanged()), - this, SIGNAL(layoutAboutToBeChanged()) ); - connect( d->mModel, SIGNAL(layoutChanged()), - this, SIGNAL(layoutChanged()) ); - connect( d->mModel, SIGNAL(modelAboutToBeReset()), - this, SIGNAL(modelAboutToBeReset()) ); - connect( d->mModel, SIGNAL(modelReset()), - this, SIGNAL(modelReset()) ); - - //Here we assume we'll always get QModelIndex() in the parameters - connect( d->mModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)) ); - connect( d->mModel, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SIGNAL(rowsInserted(QModelIndex,int,int)) ); - connect( d->mModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)) ); - connect( d->mModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SIGNAL(rowsRemoved(QModelIndex,int,int)) ); - - connect( d->mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - this, SLOT(onSelectionChanged()) ); - - d->loadSettings(); - connect( Core::Settings::self(), SIGNAL(configChanged()), - this, SLOT(loadSettings()) ); + d->mSelectionModel = selectionModel; + if ( _k_attributeInitialized.testAndSetAcquire( 0, 1 ) ) { + AttributeFactory::registerAttribute(); + } + + Akonadi::SelectionProxyModel *childrenFilter = new Akonadi::SelectionProxyModel( d->mSelectionModel, this ); + childrenFilter->setSourceModel( model ); + childrenFilter->setFilterBehavior( KSelectionProxyModel::ChildrenOfExactSelection ); + + EntityMimeTypeFilterModel *itemFilter = new EntityMimeTypeFilterModel( this ); + itemFilter->setSourceModel( childrenFilter ); + itemFilter->addMimeTypeExclusionFilter( Collection::mimeType() ); + itemFilter->addMimeTypeInclusionFilter( QLatin1String( "message/rfc822" ) ); + itemFilter->setHeaderGroup( EntityTreeModel::ItemListHeaders ); + + d->mModel = itemFilter; + + kDebug() << "Using model:" << model->metaObject()->className(); + + connect( d->mModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(onSourceDataChanged(QModelIndex,QModelIndex)) ); + + connect( d->mModel, SIGNAL(layoutAboutToBeChanged()), + this, SIGNAL(layoutAboutToBeChanged()) ); + connect( d->mModel, SIGNAL(layoutChanged()), + this, SIGNAL(layoutChanged()) ); + connect( d->mModel, SIGNAL(modelAboutToBeReset()), + this, SIGNAL(modelAboutToBeReset()) ); + connect( d->mModel, SIGNAL(modelReset()), + this, SIGNAL(modelReset()) ); + + //Here we assume we'll always get QModelIndex() in the parameters + connect( d->mModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), + this, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)) ); + connect( d->mModel, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SIGNAL(rowsInserted(QModelIndex,int,int)) ); + connect( d->mModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), + this, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)) ); + connect( d->mModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SIGNAL(rowsRemoved(QModelIndex,int,int)) ); + + connect( d->mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(onSelectionChanged()) ); + + d->loadSettings(); + connect( Core::Settings::self(), SIGNAL(configChanged()), + this, SLOT(loadSettings()) ); } StorageModel::~StorageModel() { - delete d; + delete d; } Collection::List StorageModel::displayedCollections() const { - Collection::List collections; - QModelIndexList indexes = d->mSelectionModel->selectedRows(); + Collection::List collections; + QModelIndexList indexes = d->mSelectionModel->selectedRows(); - foreach ( const QModelIndex &index, indexes ) { - Collection c = index.data( EntityTreeModel::CollectionRole ).value(); - if ( c.isValid() ) { - collections << c; + foreach ( const QModelIndex &index, indexes ) { + Collection c = index.data( EntityTreeModel::CollectionRole ).value(); + if ( c.isValid() ) { + collections << c; + } } - } - return collections; + return collections; } QString StorageModel::id() const { - QStringList ids; - QModelIndexList indexes = d->mSelectionModel->selectedRows(); + QStringList ids; + QModelIndexList indexes = d->mSelectionModel->selectedRows(); - foreach ( const QModelIndex &index, indexes ) { - Collection c = index.data( EntityTreeModel::CollectionRole ).value(); - if ( c.isValid() ) { - ids << QString::number( c.id() ); + foreach ( const QModelIndex &index, indexes ) { + Collection c = index.data( EntityTreeModel::CollectionRole ).value(); + if ( c.isValid() ) { + ids << QString::number( c.id() ); + } } - } - ids.sort(); - return ids.join(QLatin1String( ":" )); + ids.sort(); + return ids.join(QLatin1String( ":" )); } bool StorageModel::isOutBoundFolder( const Akonadi::Collection& c ) const { - if ( c.hasAttribute() - && c.attribute()->isOutboundFolder() ) { - return true; - } - return false; + if ( c.hasAttribute() + && c.attribute()->isOutboundFolder() ) { + return true; + } + return false; } bool StorageModel::containsOutboundMessages() const { - QModelIndexList indexes = d->mSelectionModel->selectedRows(); + QModelIndexList indexes = d->mSelectionModel->selectedRows(); - foreach ( const QModelIndex &index, indexes ) { - Collection c = index.data( EntityTreeModel::CollectionRole ).value(); - if ( c.isValid() ) { - return isOutBoundFolder( c ); + foreach ( const QModelIndex &index, indexes ) { + Collection c = index.data( EntityTreeModel::CollectionRole ).value(); + if ( c.isValid() ) { + return isOutBoundFolder( c ); + } } - } - return false; + return false; } int StorageModel::initialUnreadRowCountGuess() const { - QModelIndexList indexes = d->mSelectionModel->selectedRows(); + QModelIndexList indexes = d->mSelectionModel->selectedRows(); - int unreadCount = 0; + int unreadCount = 0; - foreach ( const QModelIndex &index, indexes ) { - Collection c = index.data( EntityTreeModel::CollectionRole ).value(); - if ( c.isValid() ) { - unreadCount+= c.statistics().unreadCount(); + foreach ( const QModelIndex &index, indexes ) { + Collection c = index.data( EntityTreeModel::CollectionRole ).value(); + if ( c.isValid() ) { + unreadCount+= c.statistics().unreadCount(); + } } - } - return unreadCount; + return unreadCount; } bool StorageModel::initializeMessageItem( MessageList::Core::MessageItem *mi, int row, bool bUseReceiver ) const { - const Item item = itemForRow( row ); - const KMime::Message::Ptr mail = messageForItem( item ); - if ( !mail ) { - return false; - } + const Item item = itemForRow( row ); + const KMime::Message::Ptr mail = messageForItem( item ); + if ( !mail ) { + return false; + } + + QString sender; + if ( mail->from() ) { + sender = mail->from()->asUnicodeString(); + } + QString receiver; + if ( mail->to() ) { + receiver = mail->to()->asUnicodeString(); + } - QString sender; - if ( mail->from() ) { - sender = mail->from()->asUnicodeString(); - } - QString receiver; - if ( mail->to() ) { - receiver = mail->to()->asUnicodeString(); - } - - // Static for speed reasons - static const QString noSubject = i18nc( "displayed as subject when the subject of a mail is empty", "No Subject" ); - static const QString unknown( i18nc( "displayed when a mail has unknown sender, receiver or date", "Unknown" ) ); - - if ( sender.isEmpty() ) { - sender = unknown; - } - if ( receiver.isEmpty() ) { - receiver = unknown; - } - - mi->initialSetup( mail->date()->dateTime().toTime_t(), - item.size(), - sender, receiver, - bUseReceiver ); - mi->setItemId( item.id() ); - - QString subject = mail->subject()->asUnicodeString(); - if ( subject.isEmpty() ) { - subject = QLatin1Char( '(' ) + noSubject + QLatin1Char( ')' ); - } + // Static for speed reasons + static const QString noSubject = i18nc( "displayed as subject when the subject of a mail is empty", "No Subject" ); + static const QString unknown( i18nc( "displayed when a mail has unknown sender, receiver or date", "Unknown" ) ); - mi->setSubject( subject ); + if ( sender.isEmpty() ) { + sender = unknown; + } + if ( receiver.isEmpty() ) { + receiver = unknown; + } + + mi->initialSetup( mail->date()->dateTime().toTime_t(), + item.size(), + sender, receiver, + bUseReceiver ); + mi->setItemId( item.id() ); + + QString subject = mail->subject()->asUnicodeString(); + if ( subject.isEmpty() ) { + subject = QLatin1Char( '(' ) + noSubject + QLatin1Char( ')' ); + } + + mi->setSubject( subject ); - updateMessageItemData( mi, row ); + updateMessageItemData( mi, row ); - return true; + return true; } static QByteArray md5Encode( const QByteArray &str ) { - if ( str.trimmed().isEmpty() ) return QByteArray(); + if ( str.trimmed().isEmpty() ) return QByteArray(); - QCryptographicHash c( QCryptographicHash::Md5 ); - c.addData( str.trimmed() ); - return c.result(); + QCryptographicHash c( QCryptographicHash::Md5 ); + c.addData( str.trimmed() ); + return c.result(); } void StorageModel::fillMessageItemThreadingData( MessageList::Core::MessageItem *mi, int row, ThreadingDataSubset subset ) const { - const KMime::Message::Ptr mail = messageForRow( row ); - Q_ASSERT( mail ); // We ASSUME that initializeMessageItem has been called successfully... + const KMime::Message::Ptr mail = messageForRow( row ); + Q_ASSERT( mail ); // We ASSUME that initializeMessageItem has been called successfully... - switch ( subset ) { - case PerfectThreadingReferencesAndSubject: - { - const QString subject = mail->subject()->asUnicodeString(); - const QString strippedSubject = MessageCore::StringUtil::stripOffPrefixes( subject ); - mi->setStrippedSubjectMD5( md5Encode( strippedSubject.toUtf8() ) ); - mi->setSubjectIsPrefixed( subject != strippedSubject ); - // fall through - } - case PerfectThreadingPlusReferences: - if ( !mail->references()->identifiers().isEmpty() ) { - mi->setReferencesIdMD5( md5Encode( mail->references()->identifiers().last() ) ); - } - // fall through - case PerfectThreadingOnly: - mi->setMessageIdMD5( md5Encode( mail->messageID()->identifier() ) ); - if ( !mail->inReplyTo()->identifiers().isEmpty() ) { - mi->setInReplyToIdMD5( md5Encode( mail->inReplyTo()->identifiers().first() ) ); - } - break; - default: - Q_ASSERT( false ); // should never happen - break; - } + switch ( subset ) { + case PerfectThreadingReferencesAndSubject: + { + const QString subject = mail->subject()->asUnicodeString(); + const QString strippedSubject = MessageCore::StringUtil::stripOffPrefixes( subject ); + mi->setStrippedSubjectMD5( md5Encode( strippedSubject.toUtf8() ) ); + mi->setSubjectIsPrefixed( subject != strippedSubject ); + // fall through + } + case PerfectThreadingPlusReferences: + if ( !mail->references()->identifiers().isEmpty() ) { + mi->setReferencesIdMD5( md5Encode( mail->references()->identifiers().last() ) ); + } + // fall through + case PerfectThreadingOnly: + mi->setMessageIdMD5( md5Encode( mail->messageID()->identifier() ) ); + if ( !mail->inReplyTo()->identifiers().isEmpty() ) { + mi->setInReplyToIdMD5( md5Encode( mail->inReplyTo()->identifiers().first() ) ); + } + break; + default: + Q_ASSERT( false ); // should never happen + break; + } } void StorageModel::updateMessageItemData( MessageList::Core::MessageItem *mi, int row ) const { - const Item item = itemForRow( row ); + const Item item = itemForRow( row ); - Akonadi::MessageStatus stat; - stat.setStatusFromFlags( item.flags() ); + Akonadi::MessageStatus stat; + stat.setStatusFromFlags( item.flags() ); - mi->setAkonadiItem( item ); - mi->setStatus( stat ); + mi->setAkonadiItem( item ); + mi->setStatus( stat ); - if ( stat.isEncrypted() ) - mi->setEncryptionState( Core::MessageItem::FullyEncrypted ); - else - mi->setEncryptionState( Core::MessageItem::EncryptionStateUnknown ); + if ( stat.isEncrypted() ) + mi->setEncryptionState( Core::MessageItem::FullyEncrypted ); + else + mi->setEncryptionState( Core::MessageItem::EncryptionStateUnknown ); - if ( stat.isSigned() ) - mi->setSignatureState( Core::MessageItem::FullySigned ); - else - mi->setSignatureState( Core::MessageItem::SignatureStateUnknown ); + if ( stat.isSigned() ) + mi->setSignatureState( Core::MessageItem::FullySigned ); + else + mi->setSignatureState( Core::MessageItem::SignatureStateUnknown ); - mi->invalidateTagCache(); - mi->invalidateAnnotationCache(); + mi->invalidateTagCache(); + mi->invalidateAnnotationCache(); } void StorageModel::setMessageItemStatus( MessageList::Core::MessageItem *mi, int row, const Akonadi::MessageStatus &status ) { - Q_UNUSED( mi ); - Item item = itemForRow( row ); - item.setFlags( status.statusFlags() ); - ItemModifyJob *job = new ItemModifyJob( item, this ); - job->disableRevisionCheck(); - job->setIgnorePayload( true ); + Q_UNUSED( mi ); + Item item = itemForRow( row ); + item.setFlags( status.statusFlags() ); + ItemModifyJob *job = new ItemModifyJob( item, this ); + job->disableRevisionCheck(); + job->setIgnorePayload( true ); } QVariant StorageModel::data( const QModelIndex &index, int role ) const { - // We don't provide an implementation for data() in No-Akonadi-KMail. - // This is because StorageModel must be a wrapper anyway (because columns - // must be re-mapped and functions not available in a QAbstractItemModel - // are strictly needed. So when porting to Akonadi this class will - // either wrap or subclass the MessageModel and implement initializeMessageItem() - // with appropriate calls to data(). And for No-Akonadi-KMail we still have - // a somewhat efficient implementation. + // We don't provide an implementation for data() in No-Akonadi-KMail. + // This is because StorageModel must be a wrapper anyway (because columns + // must be re-mapped and functions not available in a QAbstractItemModel + // are strictly needed. So when porting to Akonadi this class will + // either wrap or subclass the MessageModel and implement initializeMessageItem() + // with appropriate calls to data(). And for No-Akonadi-KMail we still have + // a somewhat efficient implementation. - Q_UNUSED( index ); - Q_UNUSED( role ); + Q_UNUSED( index ); + Q_UNUSED( role ); - return QVariant(); + return QVariant(); } int StorageModel::columnCount( const QModelIndex &parent ) const { - if ( !parent.isValid() ) - return 1; - return 0; // this model is flat. + if ( !parent.isValid() ) + return 1; + return 0; // this model is flat. } QModelIndex StorageModel::index( int row, int column, const QModelIndex &parent ) const { - if ( !parent.isValid() ) - return createIndex( row, column, 0 ); + if ( !parent.isValid() ) + return createIndex( row, column, 0 ); - return QModelIndex(); // this model is flat. + return QModelIndex(); // this model is flat. } QModelIndex StorageModel::parent( const QModelIndex &index ) const { - Q_UNUSED( index ); - return QModelIndex(); // this model is flat. + Q_UNUSED( index ); + return QModelIndex(); // this model is flat. } int StorageModel::rowCount( const QModelIndex &parent ) const { - if ( !parent.isValid() ) - return d->mModel->rowCount(); - return 0; // this model is flat. + if ( !parent.isValid() ) + return d->mModel->rowCount(); + return 0; // this model is flat. } QMimeData* StorageModel::mimeData( const QList< MessageList::Core::MessageItem* >& items ) const { - QMimeData *data = new QMimeData(); - KUrl::List urls; - foreach ( MessageList::Core::MessageItem* mi, items ) { - Akonadi::Item item = itemForRow( mi->currentModelIndexRow() ); - urls << item.url( Item::UrlWithMimeType ); - } + QMimeData *data = new QMimeData(); + KUrl::List urls; + foreach ( MessageList::Core::MessageItem* mi, items ) { + Akonadi::Item item = itemForRow( mi->currentModelIndexRow() ); + urls << item.url( Item::UrlWithMimeType ); + } - urls.populateMimeData( data ); + urls.populateMimeData( data ); - return data; + return data; } @@ -406,56 +406,56 @@ void StorageModel::Private::onSourceDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight ) { - emit q->dataChanged( q->index( topLeft.row(), 0 ), - q->index( bottomRight.row(), 0 ) ); + emit q->dataChanged( q->index( topLeft.row(), 0 ), + q->index( bottomRight.row(), 0 ) ); } void StorageModel::Private::onSelectionChanged() { - emit q->headerDataChanged( Qt::Horizontal, 0, q->columnCount()-1 ); + emit q->headerDataChanged( Qt::Horizontal, 0, q->columnCount()-1 ); } void StorageModel::Private::loadSettings() { - // Custom/System colors - Core::Settings *settings = Core::Settings::self(); + // Custom/System colors + Core::Settings *settings = Core::Settings::self(); - if ( MessageCore::GlobalSettings::self()->useDefaultColors() ) { - Core::MessageItem::setUnreadMessageColor( MessageList::Util::unreadDefaultMessageColor() ); - Core::MessageItem::setImportantMessageColor( MessageList::Util::importantDefaultMessageColor() ); - Core::MessageItem::setToDoMessageColor( MessageList::Util::todoDefaultMessageColor() ); - } else { - Core::MessageItem::setUnreadMessageColor( settings->unreadMessageColor() ); - Core::MessageItem::setImportantMessageColor( settings->importantMessageColor() ); - Core::MessageItem::setToDoMessageColor( settings->todoMessageColor() ); - } - - if ( MessageCore::GlobalSettings::self()->useDefaultFonts() ) { - Core::MessageItem::setGeneralFont( KGlobalSettings::generalFont() ); - Core::MessageItem::setUnreadMessageFont( KGlobalSettings::generalFont() ); - Core::MessageItem::setImportantMessageFont( KGlobalSettings::generalFont() ); - Core::MessageItem::setToDoMessageFont( KGlobalSettings::generalFont() ); - } else { - Core::MessageItem::setGeneralFont( settings->messageListFont() ); - Core::MessageItem::setUnreadMessageFont( settings->unreadMessageFont() ); - Core::MessageItem::setImportantMessageFont( settings->importantMessageFont() ); - Core::MessageItem::setToDoMessageFont( settings->todoMessageFont() ); - } + if ( MessageCore::GlobalSettings::self()->useDefaultColors() ) { + Core::MessageItem::setUnreadMessageColor( MessageList::Util::unreadDefaultMessageColor() ); + Core::MessageItem::setImportantMessageColor( MessageList::Util::importantDefaultMessageColor() ); + Core::MessageItem::setToDoMessageColor( MessageList::Util::todoDefaultMessageColor() ); + } else { + Core::MessageItem::setUnreadMessageColor( settings->unreadMessageColor() ); + Core::MessageItem::setImportantMessageColor( settings->importantMessageColor() ); + Core::MessageItem::setToDoMessageColor( settings->todoMessageColor() ); + } + + if ( MessageCore::GlobalSettings::self()->useDefaultFonts() ) { + Core::MessageItem::setGeneralFont( KGlobalSettings::generalFont() ); + Core::MessageItem::setUnreadMessageFont( KGlobalSettings::generalFont() ); + Core::MessageItem::setImportantMessageFont( KGlobalSettings::generalFont() ); + Core::MessageItem::setToDoMessageFont( KGlobalSettings::generalFont() ); + } else { + Core::MessageItem::setGeneralFont( settings->messageListFont() ); + Core::MessageItem::setUnreadMessageFont( settings->unreadMessageFont() ); + Core::MessageItem::setImportantMessageFont( settings->importantMessageFont() ); + Core::MessageItem::setToDoMessageFont( settings->todoMessageFont() ); + } } Item StorageModel::itemForRow( int row ) const { - return d->mModel->data( d->mModel->index( row, 0 ), EntityTreeModel::ItemRole ).value(); + return d->mModel->data( d->mModel->index( row, 0 ), EntityTreeModel::ItemRole ).value(); } KMime::Message::Ptr StorageModel::messageForRow( int row ) const { - return messageForItem( itemForRow( row ) ); + return messageForItem( itemForRow( row ) ); } void StorageModel::resetModelStorage() { - reset(); + reset(); } #include "moc_storagemodel.cpp" diff -Nru kdepim-4.12.97/messagelist/storagemodel.h kdepim-4.13.0/messagelist/storagemodel.h --- kdepim-4.12.97/messagelist/storagemodel.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/storagemodel.h 2014-04-10 07:40:20.000000000 +0000 @@ -39,7 +39,7 @@ namespace Core { - class MessageItem; +class MessageItem; } /** @@ -47,51 +47,51 @@ */ class MESSAGELIST_EXPORT StorageModel : public MessageList::Core::StorageModel { - Q_OBJECT + Q_OBJECT public: - /** + /** * Create a StorageModel wrapping the specified folder. */ - explicit StorageModel( QAbstractItemModel *model, QItemSelectionModel *selectionModel, QObject *parent = 0 ); - ~StorageModel(); + explicit StorageModel( QAbstractItemModel *model, QItemSelectionModel *selectionModel, QObject *parent = 0 ); + ~StorageModel(); - Akonadi::Collection::List displayedCollections() const; + Akonadi::Collection::List displayedCollections() const; - virtual QString id() const; - virtual bool containsOutboundMessages() const; + virtual QString id() const; + virtual bool containsOutboundMessages() const; - virtual bool isOutBoundFolder( const Akonadi::Collection& c ) const; + virtual bool isOutBoundFolder( const Akonadi::Collection& c ) const; - virtual int initialUnreadRowCountGuess() const; - virtual bool initializeMessageItem( MessageList::Core::MessageItem *mi, int row, bool bUseReceiver ) const; - virtual void fillMessageItemThreadingData( MessageList::Core::MessageItem *mi, int row, ThreadingDataSubset subset ) const; - virtual void updateMessageItemData( MessageList::Core::MessageItem *mi, int row ) const; - virtual void setMessageItemStatus( MessageList::Core::MessageItem *mi, int row, const Akonadi::MessageStatus &status ); + virtual int initialUnreadRowCountGuess() const; + virtual bool initializeMessageItem( MessageList::Core::MessageItem *mi, int row, bool bUseReceiver ) const; + virtual void fillMessageItemThreadingData( MessageList::Core::MessageItem *mi, int row, ThreadingDataSubset subset ) const; + virtual void updateMessageItemData( MessageList::Core::MessageItem *mi, int row ) const; + virtual void setMessageItemStatus( MessageList::Core::MessageItem *mi, int row, const Akonadi::MessageStatus &status ); - virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const; - virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; - virtual QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const; - virtual QModelIndex parent( const QModelIndex &index ) const; - virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const; + virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const; + virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; + virtual QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const; + virtual QModelIndex parent( const QModelIndex &index ) const; + virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const; - virtual QMimeData* mimeData( const QList< MessageList::Core::MessageItem* >& ) const; - using MessageList::Core::StorageModel::mimeData; + virtual QMimeData* mimeData( const QList< MessageList::Core::MessageItem* >& ) const; + using MessageList::Core::StorageModel::mimeData; - virtual void prepareForScan(); + virtual void prepareForScan(); - Akonadi::Item itemForRow( int row ) const; - KMime::Message::Ptr messageForRow( int row ) const; + Akonadi::Item itemForRow( int row ) const; + KMime::Message::Ptr messageForRow( int row ) const; - void resetModelStorage(); + void resetModelStorage(); private: - Q_PRIVATE_SLOT(d, void onSourceDataChanged( const QModelIndex&, const QModelIndex& )) - Q_PRIVATE_SLOT(d, void onSelectionChanged()) - Q_PRIVATE_SLOT(d, void loadSettings()) + Q_PRIVATE_SLOT(d, void onSourceDataChanged( const QModelIndex&, const QModelIndex& )) + Q_PRIVATE_SLOT(d, void onSelectionChanged()) + Q_PRIVATE_SLOT(d, void loadSettings()) - class Private; - Private * const d; + class Private; + Private * const d; }; } // namespace MessageList diff -Nru kdepim-4.12.97/messagelist/tests/quicksearchlinetest.cpp kdepim-4.13.0/messagelist/tests/quicksearchlinetest.cpp --- kdepim-4.12.97/messagelist/tests/quicksearchlinetest.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/tests/quicksearchlinetest.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -109,6 +109,20 @@ QCOMPARE(spy.count(), 1); } +void QuickSearchLineTest::shouldEmitSearchOptionChangedWhenUseTabPress() +{ + QuickSearchLine searchLine; + searchLine.show(); + QTest::qWaitForWindowShown(&searchLine); + QPushButton *button = qFindChild(&searchLine, QLatin1String("full_message")); + QTest::mouseClick(button, Qt::LeftButton); + QTest::keyClick(button,Qt::Key_Right); + QSignalSpy spy(&searchLine, SIGNAL(searchOptionChanged())); + button = qFindChild(&searchLine, QLatin1String("body")); + QTest::mouseClick(button, Qt::LeftButton); + QCOMPARE(spy.count(), 1); +} + void QuickSearchLineTest::shouldResetAllWhenResetFilter() { QuickSearchLine searchLine; @@ -206,7 +220,7 @@ { QuickSearchLine searchLine; QPushButton *button = qFindChild(&searchLine, QLatin1String("fromorto")); - button->setChecked(true); + QTest::mouseClick(button, Qt::LeftButton); searchLine.setContainsOutboundMessages(true); QuickSearchLine::SearchOptions options; options = QuickSearchLine::SearchAgainstTo; diff -Nru kdepim-4.12.97/messagelist/tests/quicksearchlinetest.h kdepim-4.13.0/messagelist/tests/quicksearchlinetest.h --- kdepim-4.12.97/messagelist/tests/quicksearchlinetest.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/tests/quicksearchlinetest.h 2014-04-10 07:40:20.000000000 +0000 @@ -44,6 +44,7 @@ void shouldShowMoreOptionWhenClickOnMoreButton(); void shouldChangeFromButtonLabelWhenChangeOutboundMessagesValue(); void shouldSearchToOrFrom(); + void shouldEmitSearchOptionChangedWhenUseTabPress(); }; #endif // QUICKSEARCHLINETEST_H diff -Nru kdepim-4.12.97/messagelist/utils/aggregationcombobox.cpp kdepim-4.13.0/messagelist/utils/aggregationcombobox.cpp --- kdepim-4.12.97/messagelist/utils/aggregationcombobox.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/aggregationcombobox.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -29,101 +29,101 @@ using namespace MessageList::Utils; AggregationComboBox::AggregationComboBox( QWidget * parent ) -: KComboBox( parent ), d( new AggregationComboBoxPrivate( this ) ) + : KComboBox( parent ), d( new AggregationComboBoxPrivate( this ) ) { - if( Manager::instance() ) - d->slotLoadAggregations(); - else - setEnabled(false); + if( Manager::instance() ) + d->slotLoadAggregations(); + else + setEnabled(false); } AggregationComboBox::~AggregationComboBox() { - delete d; + delete d; } QString AggregationComboBox::currentAggregation() const { - return itemData( currentIndex() ).toString(); + return itemData( currentIndex() ).toString(); } void AggregationComboBox::writeDefaultConfig() const { - KConfigGroup group( Settings::self()->config(), "MessageListView::StorageModelAggregations" ); + KConfigGroup group( Settings::self()->config(), "MessageListView::StorageModelAggregations" ); - const QString aggregationID = currentAggregation(); - group.writeEntry( QLatin1String( "DefaultSet" ), aggregationID ); + const QString aggregationID = currentAggregation(); + group.writeEntry( QLatin1String( "DefaultSet" ), aggregationID ); - Manager::instance()->aggregationsConfigurationCompleted(); + Manager::instance()->aggregationsConfigurationCompleted(); } void AggregationComboBox::writeStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool isPrivateSetting ) const { - writeStorageModelConfig( storageModel->id(), isPrivateSetting ); + writeStorageModelConfig( storageModel->id(), isPrivateSetting ); } void AggregationComboBox::writeStorageModelConfig( const QString &id, bool isPrivateSetting ) const { - // message list aggregation - QString aggregationID; - if ( isPrivateSetting ) { - aggregationID = currentAggregation(); - } else { // explicitly use default aggregation id when using default aggregation. - aggregationID = Manager::instance()->defaultAggregation()->id(); - } - Manager::instance()->saveAggregationForStorageModel( id, aggregationID, isPrivateSetting ); - Manager::instance()->aggregationsConfigurationCompleted(); + // message list aggregation + QString aggregationID; + if ( isPrivateSetting ) { + aggregationID = currentAggregation(); + } else { // explicitly use default aggregation id when using default aggregation. + aggregationID = Manager::instance()->defaultAggregation()->id(); + } + Manager::instance()->saveAggregationForStorageModel( id, aggregationID, isPrivateSetting ); + Manager::instance()->aggregationsConfigurationCompleted(); } void AggregationComboBox::writeStorageModelConfig( const Akonadi::Collection&col, bool isPrivateSetting ) const { - writeStorageModelConfig( QString::number( col.id() ), isPrivateSetting ); + writeStorageModelConfig( QString::number( col.id() ), isPrivateSetting ); } void AggregationComboBox::readStorageModelConfig( const QString & id, bool &isPrivateSetting ) { - const Aggregation *aggregation = Manager::instance()->aggregationForStorageModel( id, &isPrivateSetting ); - d->setCurrentAggregation( aggregation ); + const Aggregation *aggregation = Manager::instance()->aggregationForStorageModel( id, &isPrivateSetting ); + d->setCurrentAggregation( aggregation ); } void AggregationComboBox::readStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool &isPrivateSetting ) { - readStorageModelConfig( storageModel->id(), isPrivateSetting ); + readStorageModelConfig( storageModel->id(), isPrivateSetting ); } void AggregationComboBox::readStorageModelConfig( const Akonadi::Collection &col, bool &isPrivateSetting ) { - if ( col.isValid() ) - readStorageModelConfig( QString::number( col.id() ), isPrivateSetting ); + if ( col.isValid() ) + readStorageModelConfig( QString::number( col.id() ), isPrivateSetting ); } void AggregationComboBox::selectDefault() { - const Aggregation *defaultAggregation = Manager::instance()->defaultAggregation(); - d->setCurrentAggregation( defaultAggregation ); + const Aggregation *defaultAggregation = Manager::instance()->defaultAggregation(); + d->setCurrentAggregation( defaultAggregation ); } void AggregationComboBoxPrivate::slotLoadAggregations() { - q->clear(); + q->clear(); - // Get all message list aggregations and sort them into alphabetical order. - QList< Aggregation * > aggregations = Manager::instance()->aggregations().values(); - qSort( aggregations.begin(), aggregations.end(), MessageList::Core::Aggregation::compareName ); - - foreach( const Aggregation * aggregation, aggregations ) - { - q->addItem( aggregation->name(), QVariant( aggregation->id() ) ); - } + // Get all message list aggregations and sort them into alphabetical order. + QList< Aggregation * > aggregations = Manager::instance()->aggregations().values(); + qSort( aggregations.begin(), aggregations.end(), MessageList::Core::Aggregation::compareName ); + + foreach( const Aggregation * aggregation, aggregations ) + { + q->addItem( aggregation->name(), QVariant( aggregation->id() ) ); + } } void AggregationComboBoxPrivate::setCurrentAggregation( const Aggregation *aggregation ) { - Q_ASSERT( aggregation != 0 ); + Q_ASSERT( aggregation != 0 ); - const QString aggregationID = aggregation->id(); - const int aggregationIndex = q->findData( QVariant( aggregationID ) ); - q->setCurrentIndex( aggregationIndex ); + const QString aggregationID = aggregation->id(); + const int aggregationIndex = q->findData( QVariant( aggregationID ) ); + q->setCurrentIndex( aggregationIndex ); } #include "moc_aggregationcombobox.cpp" diff -Nru kdepim-4.12.97/messagelist/utils/aggregationcombobox.h kdepim-4.13.0/messagelist/utils/aggregationcombobox.h --- kdepim-4.12.97/messagelist/utils/aggregationcombobox.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/aggregationcombobox.h 2014-04-10 07:40:20.000000000 +0000 @@ -42,31 +42,31 @@ */ class MESSAGELIST_EXPORT AggregationComboBox : public KComboBox { - Q_OBJECT + Q_OBJECT public: - explicit AggregationComboBox( QWidget * parent ); - ~AggregationComboBox(); + explicit AggregationComboBox( QWidget * parent ); + ~AggregationComboBox(); - QString currentAggregation() const; + QString currentAggregation() const; - void writeDefaultConfig() const; + void writeDefaultConfig() const; - void writeStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool isPrivateSetting ) const; - void writeStorageModelConfig( const Akonadi::Collection &col, bool isPrivateSetting ) const; - void writeStorageModelConfig( const QString &id, bool isPrivateSetting ) const; + void writeStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool isPrivateSetting ) const; + void writeStorageModelConfig( const Akonadi::Collection &col, bool isPrivateSetting ) const; + void writeStorageModelConfig( const QString &id, bool isPrivateSetting ) const; - void readStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool &isPrivateSetting ); - void readStorageModelConfig( const Akonadi::Collection &col, bool &isPrivateSetting ); - void readStorageModelConfig( const QString &id, bool &isPrivateSetting ); + void readStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool &isPrivateSetting ); + void readStorageModelConfig( const Akonadi::Collection &col, bool &isPrivateSetting ); + void readStorageModelConfig( const QString &id, bool &isPrivateSetting ); public Q_SLOTS: - void selectDefault(); + void selectDefault(); private: - Q_PRIVATE_SLOT(d, void slotLoadAggregations()) + Q_PRIVATE_SLOT(d, void slotLoadAggregations()) - AggregationComboBoxPrivate * const d; + AggregationComboBoxPrivate * const d; }; } // namespace Utils diff -Nru kdepim-4.12.97/messagelist/utils/aggregationconfigbutton.cpp kdepim-4.13.0/messagelist/utils/aggregationconfigbutton.cpp --- kdepim-4.12.97/messagelist/utils/aggregationconfigbutton.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/aggregationconfigbutton.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -31,48 +31,48 @@ class MessageList::Utils::AggregationConfigButtonPrivate { public: - AggregationConfigButtonPrivate( AggregationConfigButton *owner ) - : q( owner ), mAggregationComboBox( 0 ) { } + AggregationConfigButtonPrivate( AggregationConfigButton *owner ) + : q( owner ), mAggregationComboBox( 0 ) { } - AggregationConfigButton * const q; + AggregationConfigButton * const q; - const AggregationComboBox * mAggregationComboBox; + const AggregationComboBox * mAggregationComboBox; - void slotConfigureAggregations(); + void slotConfigureAggregations(); }; AggregationConfigButton::AggregationConfigButton( QWidget * parent, const AggregationComboBox * aggregationComboBox ) -: KPushButton( i18n( "Configure..." ), parent ), d( new AggregationConfigButtonPrivate( this ) ) + : KPushButton( i18n( "Configure..." ), parent ), d( new AggregationConfigButtonPrivate( this ) ) { - d->mAggregationComboBox = aggregationComboBox; - connect( this, SIGNAL(pressed()), - this, SLOT(slotConfigureAggregations()) ); - - // Keep aggregation combo up-to-date with any changes made in the configure dialog. - if ( d->mAggregationComboBox != 0 ) - connect( this, SIGNAL(configureDialogCompleted()), - d->mAggregationComboBox, SLOT(slotLoadAggregations()) ); + d->mAggregationComboBox = aggregationComboBox; + connect( this, SIGNAL(pressed()), + this, SLOT(slotConfigureAggregations()) ); + + // Keep aggregation combo up-to-date with any changes made in the configure dialog. + if ( d->mAggregationComboBox != 0 ) + connect( this, SIGNAL(configureDialogCompleted()), + d->mAggregationComboBox, SLOT(slotLoadAggregations()) ); } AggregationConfigButton::~AggregationConfigButton() { - delete d; + delete d; } void AggregationConfigButtonPrivate::slotConfigureAggregations() { - QString currentAggregationID; - if ( mAggregationComboBox ) { - currentAggregationID = mAggregationComboBox->currentAggregation(); - } + QString currentAggregationID; + if ( mAggregationComboBox ) { + currentAggregationID = mAggregationComboBox->currentAggregation(); + } - ConfigureAggregationsDialog *dialog = new ConfigureAggregationsDialog( q->window() ); - dialog->selectAggregation( currentAggregationID ); + ConfigureAggregationsDialog *dialog = new ConfigureAggregationsDialog( q->window() ); + dialog->selectAggregation( currentAggregationID ); - QObject::connect( dialog, SIGNAL(okClicked()), - q, SIGNAL(configureDialogCompleted()) ); + QObject::connect( dialog, SIGNAL(okClicked()), + q, SIGNAL(configureDialogCompleted()) ); - dialog->show(); + dialog->show(); } #include "moc_aggregationconfigbutton.cpp" diff -Nru kdepim-4.12.97/messagelist/utils/aggregationconfigbutton.h kdepim-4.13.0/messagelist/utils/aggregationconfigbutton.h --- kdepim-4.12.97/messagelist/utils/aggregationconfigbutton.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/aggregationconfigbutton.h 2014-04-10 07:40:20.000000000 +0000 @@ -37,27 +37,27 @@ */ class MESSAGELIST_EXPORT AggregationConfigButton : public KPushButton { - Q_OBJECT + Q_OBJECT public: - /** Constructor. + /** Constructor. * @param parent The parent widget for the button. * @param aggregationComboBox Optional AggregationComboBox to be kept in sync * with changes made by the configure dialog. */ - explicit AggregationConfigButton( QWidget * parent, const AggregationComboBox * aggregationComboBox = 0 ); - ~AggregationConfigButton(); + explicit AggregationConfigButton( QWidget * parent, const AggregationComboBox * aggregationComboBox = 0 ); + ~AggregationConfigButton(); signals: - /** + /** * A signal emitted when configure dialog has been successfully completed. */ - void configureDialogCompleted(); + void configureDialogCompleted(); private: - Q_PRIVATE_SLOT(d, void slotConfigureAggregations()) + Q_PRIVATE_SLOT(d, void slotConfigureAggregations()) - AggregationConfigButtonPrivate * const d; + AggregationConfigButtonPrivate * const d; }; } // namespace Utils diff -Nru kdepim-4.12.97/messagelist/utils/aggregationeditor.cpp kdepim-4.13.0/messagelist/utils/aggregationeditor.cpp --- kdepim-4.12.97/messagelist/utils/aggregationeditor.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/aggregationeditor.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -38,64 +38,64 @@ using namespace MessageList::Core; AggregationEditor::AggregationEditor( QWidget *parent ) - : OptionSetEditor( parent ) + : OptionSetEditor( parent ) { - mCurrentAggregation = 0; + mCurrentAggregation = 0; - // Grouping and Threading tab - QWidget * tab = new QWidget( this ); - addTab( tab, i18n( "Groups && Threading" ) ); + // Grouping and Threading tab + QWidget * tab = new QWidget( this ); + addTab( tab, i18n( "Groups && Threading" ) ); - QGridLayout * tabg = new QGridLayout( tab ); + QGridLayout * tabg = new QGridLayout( tab ); - tabg->addWidget( new QLabel( i18n( "Grouping:" ), tab ), 0, 0 ); - mGroupingCombo = new KComboBox( tab ); - tabg->addWidget( mGroupingCombo, 0, 1 ); + tabg->addWidget( new QLabel( i18n( "Grouping:" ), tab ), 0, 0 ); + mGroupingCombo = new KComboBox( tab ); + tabg->addWidget( mGroupingCombo, 0, 1 ); - connect( mGroupingCombo, SIGNAL(activated(int)), - SLOT(groupingComboActivated(int)) ); + connect( mGroupingCombo, SIGNAL(activated(int)), + SLOT(groupingComboActivated(int)) ); - tabg->addWidget( new QLabel( i18n( "Group expand policy:" ), tab ), 3, 0 ); - mGroupExpandPolicyCombo = new KComboBox( tab ); - tabg->addWidget( mGroupExpandPolicyCombo, 3, 1 ); + tabg->addWidget( new QLabel( i18n( "Group expand policy:" ), tab ), 3, 0 ); + mGroupExpandPolicyCombo = new KComboBox( tab ); + tabg->addWidget( mGroupExpandPolicyCombo, 3, 1 ); - tabg->addWidget( new QLabel( i18n( "Threading:" ), tab ), 4, 0 ); - mThreadingCombo = new KComboBox( tab ); - tabg->addWidget( mThreadingCombo, 4, 1 ); + tabg->addWidget( new QLabel( i18n( "Threading:" ), tab ), 4, 0 ); + mThreadingCombo = new KComboBox( tab ); + tabg->addWidget( mThreadingCombo, 4, 1 ); - connect( mThreadingCombo, SIGNAL(activated(int)), - SLOT(threadingComboActivated(int)) ); + connect( mThreadingCombo, SIGNAL(activated(int)), + SLOT(threadingComboActivated(int)) ); - tabg->addWidget( new QLabel( i18n( "Thread leader:" ), tab ), 5, 0 ); - mThreadLeaderCombo = new KComboBox( tab ); - tabg->addWidget( mThreadLeaderCombo, 5, 1 ); + tabg->addWidget( new QLabel( i18n( "Thread leader:" ), tab ), 5, 0 ); + mThreadLeaderCombo = new KComboBox( tab ); + tabg->addWidget( mThreadLeaderCombo, 5, 1 ); - tabg->addWidget( new QLabel( i18n( "Thread expand policy:" ), tab ), 6, 0 ); - mThreadExpandPolicyCombo = new KComboBox( tab ); - tabg->addWidget( mThreadExpandPolicyCombo, 6, 1 ); + tabg->addWidget( new QLabel( i18n( "Thread expand policy:" ), tab ), 6, 0 ); + mThreadExpandPolicyCombo = new KComboBox( tab ); + tabg->addWidget( mThreadExpandPolicyCombo, 6, 1 ); - tabg->setColumnStretch( 1, 1 ); - tabg->setRowStretch( 9, 1 ); + tabg->setColumnStretch( 1, 1 ); + tabg->setRowStretch( 9, 1 ); - // Advanced tab - tab = new QWidget( this ); - addTab( tab, i18nc( "@title:tab Advanced settings tab for aggregation mode", "Advanced" ) ); + // Advanced tab + tab = new QWidget( this ); + addTab( tab, i18nc( "@title:tab Advanced settings tab for aggregation mode", "Advanced" ) ); - tabg = new QGridLayout( tab ); + tabg = new QGridLayout( tab ); - tabg->addWidget( new QLabel( i18n( "Fill view strategy:" ), tab ), 0, 0 ); - mFillViewStrategyCombo = new KComboBox( tab ); - tabg->addWidget( mFillViewStrategyCombo, 0, 1 ); + tabg->addWidget( new QLabel( i18n( "Fill view strategy:" ), tab ), 0, 0 ); + mFillViewStrategyCombo = new KComboBox( tab ); + tabg->addWidget( mFillViewStrategyCombo, 0, 1 ); - tabg->setColumnStretch( 1, 1 ); - tabg->setRowStretch( 1, 1 ); - fillGroupingCombo(); - fillThreadingCombo(); - fillFillViewStrategyCombo(); + tabg->setColumnStretch( 1, 1 ); + tabg->setRowStretch( 1, 1 ); + fillGroupingCombo(); + fillThreadingCombo(); + fillFillViewStrategyCombo(); - fillThreadLeaderCombo(); - fillThreadExpandPolicyCombo(); - fillGroupExpandPolicyCombo(); + fillThreadLeaderCombo(); + fillThreadExpandPolicyCombo(); + fillGroupExpandPolicyCombo(); } AggregationEditor::~AggregationEditor() @@ -104,159 +104,159 @@ void AggregationEditor::editAggregation( Aggregation *set ) { - mCurrentAggregation = set; + mCurrentAggregation = set; - if ( !mCurrentAggregation ) - { - setEnabled( false ); - return; - } - setEnabled( true ); - nameEdit()->setText( set->name() ); - descriptionEdit()->setText( set->description() ); - - ComboBoxUtils::setIntegerOptionComboValue( mGroupingCombo, (int)mCurrentAggregation->grouping() ); - ComboBoxUtils::setIntegerOptionComboValue( mThreadingCombo, - (int)mCurrentAggregation->threading() ); - ComboBoxUtils::setIntegerOptionComboValue( mFillViewStrategyCombo, - (int)mCurrentAggregation->fillViewStrategy() ); - - //Necessary to fill after apply mGroupingCombo/mThreadingCombo/mFillViewStrategyCombo otherwise other combo are not filled. - fillThreadLeaderCombo(); - fillThreadExpandPolicyCombo(); - fillGroupExpandPolicyCombo(); - - ComboBoxUtils::setIntegerOptionComboValue( mThreadLeaderCombo, - (int)mCurrentAggregation->threadLeader() ); - - ComboBoxUtils::setIntegerOptionComboValue( mThreadExpandPolicyCombo, - (int)mCurrentAggregation->threadExpandPolicy() ); - - ComboBoxUtils::setIntegerOptionComboValue( mGroupExpandPolicyCombo, - (int)mCurrentAggregation->groupExpandPolicy() ); - fillThreadLeaderCombo(); - fillThreadExpandPolicyCombo(); - fillGroupExpandPolicyCombo(); + if ( !mCurrentAggregation ) + { + setEnabled( false ); + return; + } + setEnabled( true ); + nameEdit()->setText( set->name() ); + descriptionEdit()->setText( set->description() ); + + ComboBoxUtils::setIntegerOptionComboValue( mGroupingCombo, (int)mCurrentAggregation->grouping() ); + ComboBoxUtils::setIntegerOptionComboValue( mThreadingCombo, + (int)mCurrentAggregation->threading() ); + ComboBoxUtils::setIntegerOptionComboValue( mFillViewStrategyCombo, + (int)mCurrentAggregation->fillViewStrategy() ); + + //Necessary to fill after apply mGroupingCombo/mThreadingCombo/mFillViewStrategyCombo otherwise other combo are not filled. + fillThreadLeaderCombo(); + fillThreadExpandPolicyCombo(); + fillGroupExpandPolicyCombo(); + + ComboBoxUtils::setIntegerOptionComboValue( mThreadLeaderCombo, + (int)mCurrentAggregation->threadLeader() ); + + ComboBoxUtils::setIntegerOptionComboValue( mThreadExpandPolicyCombo, + (int)mCurrentAggregation->threadExpandPolicy() ); + + ComboBoxUtils::setIntegerOptionComboValue( mGroupExpandPolicyCombo, + (int)mCurrentAggregation->groupExpandPolicy() ); + fillThreadLeaderCombo(); + fillThreadExpandPolicyCombo(); + fillGroupExpandPolicyCombo(); - setReadOnly( mCurrentAggregation->readOnly() ); + setReadOnly( mCurrentAggregation->readOnly() ); } void AggregationEditor::setReadOnly(bool readOnly) { - mGroupingCombo->setEnabled(!readOnly); - mGroupExpandPolicyCombo->setEnabled(!readOnly); - mThreadingCombo->setEnabled(!readOnly); - mThreadLeaderCombo->setEnabled(!readOnly); - mThreadExpandPolicyCombo->setEnabled(!readOnly); - mFillViewStrategyCombo->setEnabled(!readOnly); + mGroupingCombo->setEnabled(!readOnly); + mGroupExpandPolicyCombo->setEnabled(!readOnly); + mThreadingCombo->setEnabled(!readOnly); + mThreadLeaderCombo->setEnabled(!readOnly); + mThreadExpandPolicyCombo->setEnabled(!readOnly); + mFillViewStrategyCombo->setEnabled(!readOnly); - OptionSetEditor::setReadOnly(readOnly); + OptionSetEditor::setReadOnly(readOnly); } void AggregationEditor::commit() { - mCurrentAggregation->setName( nameEdit()->text() ); - mCurrentAggregation->setDescription( descriptionEdit()->toPlainText() ); + mCurrentAggregation->setName( nameEdit()->text() ); + mCurrentAggregation->setDescription( descriptionEdit()->toPlainText() ); - mCurrentAggregation->setGrouping( - (Aggregation::Grouping)ComboBoxUtils::getIntegerOptionComboValue( mGroupingCombo, 0 ) - ); + mCurrentAggregation->setGrouping( + (Aggregation::Grouping)ComboBoxUtils::getIntegerOptionComboValue( mGroupingCombo, 0 ) + ); - mCurrentAggregation->setGroupExpandPolicy( - (Aggregation::GroupExpandPolicy)ComboBoxUtils::getIntegerOptionComboValue( mGroupExpandPolicyCombo, 0 ) - ); + mCurrentAggregation->setGroupExpandPolicy( + (Aggregation::GroupExpandPolicy)ComboBoxUtils::getIntegerOptionComboValue( mGroupExpandPolicyCombo, 0 ) + ); - mCurrentAggregation->setThreading( - (Aggregation::Threading)ComboBoxUtils::getIntegerOptionComboValue( mThreadingCombo, 0 ) - ); + mCurrentAggregation->setThreading( + (Aggregation::Threading)ComboBoxUtils::getIntegerOptionComboValue( mThreadingCombo, 0 ) + ); - mCurrentAggregation->setThreadLeader( - (Aggregation::ThreadLeader)ComboBoxUtils::getIntegerOptionComboValue( mThreadLeaderCombo, 0 ) - ); + mCurrentAggregation->setThreadLeader( + (Aggregation::ThreadLeader)ComboBoxUtils::getIntegerOptionComboValue( mThreadLeaderCombo, 0 ) + ); - mCurrentAggregation->setThreadExpandPolicy( - (Aggregation::ThreadExpandPolicy)ComboBoxUtils::getIntegerOptionComboValue( mThreadExpandPolicyCombo, 0 ) - ); + mCurrentAggregation->setThreadExpandPolicy( + (Aggregation::ThreadExpandPolicy)ComboBoxUtils::getIntegerOptionComboValue( mThreadExpandPolicyCombo, 0 ) + ); - mCurrentAggregation->setFillViewStrategy( - (Aggregation::FillViewStrategy)ComboBoxUtils::getIntegerOptionComboValue( mFillViewStrategyCombo, 0 ) - ); + mCurrentAggregation->setFillViewStrategy( + (Aggregation::FillViewStrategy)ComboBoxUtils::getIntegerOptionComboValue( mFillViewStrategyCombo, 0 ) + ); } void AggregationEditor::slotNameEditTextEdited( const QString &newName ) { - if( !mCurrentAggregation ) - return; - mCurrentAggregation->setName( newName ); - emit aggregationNameChanged(); + if( !mCurrentAggregation ) + return; + mCurrentAggregation->setName( newName ); + emit aggregationNameChanged(); } void AggregationEditor::fillGroupingCombo() { - ComboBoxUtils::fillIntegerOptionCombo( - mGroupingCombo, - Aggregation::enumerateGroupingOptions() - ); + ComboBoxUtils::fillIntegerOptionCombo( + mGroupingCombo, + Aggregation::enumerateGroupingOptions() + ); } void AggregationEditor::groupingComboActivated( int ) { - fillGroupExpandPolicyCombo(); - fillThreadLeaderCombo(); + fillGroupExpandPolicyCombo(); + fillThreadLeaderCombo(); } void AggregationEditor::fillGroupExpandPolicyCombo() { - ComboBoxUtils::fillIntegerOptionCombo( - mGroupExpandPolicyCombo, - Aggregation::enumerateGroupExpandPolicyOptions( - (Aggregation::Grouping) ComboBoxUtils::getIntegerOptionComboValue( mGroupingCombo, Aggregation::NoGrouping ) - ) - ); + ComboBoxUtils::fillIntegerOptionCombo( + mGroupExpandPolicyCombo, + Aggregation::enumerateGroupExpandPolicyOptions( + (Aggregation::Grouping) ComboBoxUtils::getIntegerOptionComboValue( mGroupingCombo, Aggregation::NoGrouping ) + ) + ); } void AggregationEditor::fillThreadingCombo() { - ComboBoxUtils::fillIntegerOptionCombo( - mThreadingCombo, - Aggregation::enumerateThreadingOptions() - ); + ComboBoxUtils::fillIntegerOptionCombo( + mThreadingCombo, + Aggregation::enumerateThreadingOptions() + ); } void AggregationEditor::threadingComboActivated( int ) { - fillThreadLeaderCombo(); - fillThreadExpandPolicyCombo(); + fillThreadLeaderCombo(); + fillThreadExpandPolicyCombo(); } void AggregationEditor::fillThreadLeaderCombo() { - ComboBoxUtils::fillIntegerOptionCombo( - mThreadLeaderCombo, - Aggregation::enumerateThreadLeaderOptions( - (Aggregation::Grouping) ComboBoxUtils::getIntegerOptionComboValue( mGroupingCombo, Aggregation::NoGrouping ), - (Aggregation::Threading) ComboBoxUtils::getIntegerOptionComboValue( mThreadingCombo, Aggregation::NoThreading ) - ) - ); + ComboBoxUtils::fillIntegerOptionCombo( + mThreadLeaderCombo, + Aggregation::enumerateThreadLeaderOptions( + (Aggregation::Grouping) ComboBoxUtils::getIntegerOptionComboValue( mGroupingCombo, Aggregation::NoGrouping ), + (Aggregation::Threading) ComboBoxUtils::getIntegerOptionComboValue( mThreadingCombo, Aggregation::NoThreading ) + ) + ); } void AggregationEditor::fillThreadExpandPolicyCombo() { - ComboBoxUtils::fillIntegerOptionCombo( - mThreadExpandPolicyCombo, - Aggregation::enumerateThreadExpandPolicyOptions( - (Aggregation::Threading) ComboBoxUtils::getIntegerOptionComboValue( mThreadingCombo, Aggregation::NoThreading ) - ) - ); + ComboBoxUtils::fillIntegerOptionCombo( + mThreadExpandPolicyCombo, + Aggregation::enumerateThreadExpandPolicyOptions( + (Aggregation::Threading) ComboBoxUtils::getIntegerOptionComboValue( mThreadingCombo, Aggregation::NoThreading ) + ) + ); } void AggregationEditor::fillFillViewStrategyCombo() { - ComboBoxUtils::fillIntegerOptionCombo( - mFillViewStrategyCombo, - Aggregation::enumerateFillViewStrategyOptions() - ); + ComboBoxUtils::fillIntegerOptionCombo( + mFillViewStrategyCombo, + Aggregation::enumerateFillViewStrategyOptions() + ); } diff -Nru kdepim-4.12.97/messagelist/utils/aggregationeditor.h kdepim-4.13.0/messagelist/utils/aggregationeditor.h --- kdepim-4.12.97/messagelist/utils/aggregationeditor.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/aggregationeditor.h 2014-04-10 07:40:20.000000000 +0000 @@ -45,70 +45,70 @@ */ class AggregationEditor : public OptionSetEditor { - Q_OBJECT + Q_OBJECT public: - explicit AggregationEditor( QWidget *parent ); - ~AggregationEditor(); + explicit AggregationEditor( QWidget *parent ); + ~AggregationEditor(); private: - Core::Aggregation * mCurrentAggregation; // shallow, may be null! + Core::Aggregation * mCurrentAggregation; // shallow, may be null! - // Grouping, Threading and Sorting tab - KComboBox * mGroupingCombo; - KComboBox * mGroupExpandPolicyCombo; - KComboBox * mThreadingCombo; - KComboBox * mThreadLeaderCombo; - KComboBox * mThreadExpandPolicyCombo; - // Advanced tab - KComboBox * mFillViewStrategyCombo; + // Grouping, Threading and Sorting tab + KComboBox * mGroupingCombo; + KComboBox * mGroupExpandPolicyCombo; + KComboBox * mThreadingCombo; + KComboBox * mThreadLeaderCombo; + KComboBox * mThreadExpandPolicyCombo; + // Advanced tab + KComboBox * mFillViewStrategyCombo; public: - /** + /** * Sets the Aggregation to be edited. * Saves and forgets any previously Aggregation that was being edited. * The set parameter may be 0: in this case the editor is simply disabled. */ - void editAggregation( Core::Aggregation *set ); + void editAggregation( Core::Aggregation *set ); - /** + /** * Returns the Aggregation currently edited by this AggregationEditor. * May be 0. */ - Core::Aggregation * editedAggregation() const + Core::Aggregation * editedAggregation() const { return mCurrentAggregation; } - /** + /** * Explicitly commits the changes in the editor to the edited Aggregation, if any. */ - void commit(); + void commit(); signals: - /** + /** * This is triggered when the aggregation name changes in the editor text field. * It's connected to the Aggregation configuration dialog which updates * the list of aggregations with the new name. */ - void aggregationNameChanged(); + void aggregationNameChanged(); private: - // Helpers for filling the various editing elements + // Helpers for filling the various editing elements - void fillGroupingCombo(); - void fillGroupExpandPolicyCombo(); - void fillThreadingCombo(); - void fillThreadLeaderCombo(); - void fillThreadExpandPolicyCombo(); - void fillFillViewStrategyCombo(); - void setReadOnly(bool readOnly); + void fillGroupingCombo(); + void fillGroupExpandPolicyCombo(); + void fillThreadingCombo(); + void fillThreadLeaderCombo(); + void fillThreadExpandPolicyCombo(); + void fillFillViewStrategyCombo(); + void setReadOnly(bool readOnly); private slots: - // Internal handlers for editing element interaction + // Internal handlers for editing element interaction - void groupingComboActivated( int idx ); - void threadingComboActivated( int idx ); - virtual void slotNameEditTextEdited( const QString &newName ); + void groupingComboActivated( int idx ); + void threadingComboActivated( int idx ); + virtual void slotNameEditTextEdited( const QString &newName ); }; diff -Nru kdepim-4.12.97/messagelist/utils/comboboxutils.cpp kdepim-4.13.0/messagelist/utils/comboboxutils.cpp --- kdepim-4.12.97/messagelist/utils/comboboxutils.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/comboboxutils.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -28,57 +28,57 @@ void ComboBoxUtils::fillIntegerOptionCombo( KComboBox *combo, const QList< QPair< QString, int > > &optionDescriptors ) { - int val = getIntegerOptionComboValue( combo, -1 ); - combo->clear(); - int valIdx = -1; - int idx = 0; - - QList< QPair< QString, int > >::ConstIterator end( optionDescriptors.end() ); - - for( QList< QPair< QString, int > >::ConstIterator it = optionDescriptors.constBegin(); it != end; ++it ) - { - if ( val == (*it).second ) - valIdx = idx; - combo->addItem( (*it).first, QVariant( (*it).second ) ); - ++idx; - } - if ( idx == 0) - { - combo->addItem( QLatin1String("-"), QVariant( (int)0 ) ); // always default to 0 - combo->setEnabled( false ); - } else { - if ( !combo->isEnabled() ) - combo->setEnabled( true ); - if ( valIdx >= 0 ) - combo->setCurrentIndex( valIdx ); - if ( combo->count() == 1 ) - combo->setEnabled( false ); // disable when there is no choice - } + int val = getIntegerOptionComboValue( combo, -1 ); + combo->clear(); + int valIdx = -1; + int idx = 0; + + QList< QPair< QString, int > >::ConstIterator end( optionDescriptors.end() ); + + for( QList< QPair< QString, int > >::ConstIterator it = optionDescriptors.constBegin(); it != end; ++it ) + { + if ( val == (*it).second ) + valIdx = idx; + combo->addItem( (*it).first, QVariant( (*it).second ) ); + ++idx; + } + if ( idx == 0) + { + combo->addItem( QLatin1String("-"), QVariant( (int)0 ) ); // always default to 0 + combo->setEnabled( false ); + } else { + if ( !combo->isEnabled() ) + combo->setEnabled( true ); + if ( valIdx >= 0 ) + combo->setCurrentIndex( valIdx ); + if ( combo->count() == 1 ) + combo->setEnabled( false ); // disable when there is no choice + } } void ComboBoxUtils::setIntegerOptionComboValue( KComboBox *combo, int value ) { - if(combo->itemData(combo->currentIndex()).toInt() == value) { - return; - } - int index = combo->findData(value); - if(index!=-1) - combo->setCurrentIndex( index ); - else - combo->setCurrentIndex( 0 ); // default + if(combo->itemData(combo->currentIndex()).toInt() == value) { + return; + } + int index = combo->findData(value); + if(index!=-1) + combo->setCurrentIndex( index ); + else + combo->setCurrentIndex( 0 ); // default } int ComboBoxUtils::getIntegerOptionComboValue( KComboBox *combo, int defaultValue ) { - const int idx = combo->currentIndex(); - if ( idx < 0 ) - return defaultValue; - - QVariant data = combo->itemData( idx ); - bool ok; - const int val = data.toInt( &ok ); - if ( !ok ) - return defaultValue; - return val; + const int idx = combo->currentIndex(); + if ( idx < 0 ) + return defaultValue; + + QVariant data = combo->itemData( idx ); + bool ok; + const int val = data.toInt( &ok ); + if ( !ok ) + return defaultValue; + return val; } diff -Nru kdepim-4.12.97/messagelist/utils/comboboxutils.h kdepim-4.13.0/messagelist/utils/comboboxutils.h --- kdepim-4.12.97/messagelist/utils/comboboxutils.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/comboboxutils.h 2014-04-10 07:40:20.000000000 +0000 @@ -37,24 +37,24 @@ */ namespace ComboBoxUtils { - /** +/** * Fills the specified KComboBox with the options available in optionDescriptors. * Each option descriptor contains a description string and a distinct integer (possibly enum) * identifier value. */ - void fillIntegerOptionCombo( KComboBox *combo, const QList< QPair< QString, int > > &optionDescriptors ); +void fillIntegerOptionCombo( KComboBox *combo, const QList< QPair< QString, int > > &optionDescriptors ); - /** +/** * Returns the identifier of the currently selected option in the specified combo. * If the combo has no current selection or something goes wrong then the defaultValue * is returned instead. */ - int getIntegerOptionComboValue( KComboBox *combo, int defaultValue ); +int getIntegerOptionComboValue( KComboBox *combo, int defaultValue ); - /** +/** * Sets the currently selected option in the specified combo. */ - void setIntegerOptionComboValue( KComboBox *combo, int value ); +void setIntegerOptionComboValue( KComboBox *combo, int value ); } // namespace ComboBoxUtils diff -Nru kdepim-4.12.97/messagelist/utils/configureaggregationsdialog.cpp kdepim-4.13.0/messagelist/utils/configureaggregationsdialog.cpp --- kdepim-4.12.97/messagelist/utils/configureaggregationsdialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/configureaggregationsdialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -45,23 +45,23 @@ class AggregationListWidgetItem : public QListWidgetItem { private: - Core::Aggregation * mAggregation; + Core::Aggregation * mAggregation; public: - AggregationListWidgetItem( QListWidget * par, const Core::Aggregation &set ) - : QListWidgetItem( set.name(), par ) - { - mAggregation = new Core::Aggregation( set ); - } - ~AggregationListWidgetItem() - { - delete mAggregation; - } + AggregationListWidgetItem( QListWidget * par, const Core::Aggregation &set ) + : QListWidgetItem( set.name(), par ) + { + mAggregation = new Core::Aggregation( set ); + } + ~AggregationListWidgetItem() + { + delete mAggregation; + } public: - Core::Aggregation * aggregation() const + Core::Aggregation * aggregation() const { return mAggregation; } - void forgetAggregation() + void forgetAggregation() { mAggregation = 0; } }; @@ -73,14 +73,14 @@ class AggregationListWidget : public QListWidget { public: - AggregationListWidget( QWidget * parent ) - : QListWidget( parent ) - { - } + AggregationListWidget( QWidget * parent ) + : QListWidget( parent ) + { + } public: - // need a larger but shorter QListWidget - QSize sizeHint() const + // need a larger but shorter QListWidget + QSize sizeHint() const { return QSize( 450, 128 ); } }; @@ -92,360 +92,360 @@ using namespace MessageList::Utils; ConfigureAggregationsDialog::ConfigureAggregationsDialog( QWidget *parent ) - : KDialog( parent ), d( new Private( this ) ) + : KDialog( parent ), d( new Private( this ) ) { - setAttribute( Qt::WA_DeleteOnClose ); - setWindowModality( Qt::ApplicationModal ); // FIXME: Sure ? - setButtons( Ok | Cancel ); - setWindowTitle( i18n( "Customize Message Aggregation Modes" ) ); + setAttribute( Qt::WA_DeleteOnClose ); + setWindowModality( Qt::ApplicationModal ); // FIXME: Sure ? + setButtons( Ok | Cancel ); + setWindowTitle( i18n( "Customize Message Aggregation Modes" ) ); - QWidget * base = new QWidget( this ); - setMainWidget( base ); + QWidget * base = new QWidget( this ); + setMainWidget( base ); - QGridLayout * g = new QGridLayout( base ); + QGridLayout * g = new QGridLayout( base ); - d->mAggregationList = new AggregationListWidget( base ); - d->mAggregationList->setSelectionMode(QAbstractItemView::ExtendedSelection); - d->mAggregationList->setSortingEnabled( true ); - g->addWidget( d->mAggregationList, 0, 0, 7, 1 ); + d->mAggregationList = new AggregationListWidget( base ); + d->mAggregationList->setSelectionMode(QAbstractItemView::ExtendedSelection); + d->mAggregationList->setSortingEnabled( true ); + g->addWidget( d->mAggregationList, 0, 0, 7, 1 ); - connect( d->mAggregationList, SIGNAL(itemClicked(QListWidgetItem*)), - SLOT(aggregationListItemClicked(QListWidgetItem*))); + connect( d->mAggregationList, SIGNAL(itemClicked(QListWidgetItem*)), + SLOT(aggregationListItemClicked(QListWidgetItem*))); - d->mNewAggregationButton = new QPushButton( i18n( "New Aggregation" ), base ); - d->mNewAggregationButton->setIcon( KIcon( QLatin1String( "document-new" ) ) ); - d->mNewAggregationButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); - g->addWidget( d->mNewAggregationButton, 0, 1 ); + d->mNewAggregationButton = new QPushButton( i18n( "New Aggregation" ), base ); + d->mNewAggregationButton->setIcon( KIcon( QLatin1String( "document-new" ) ) ); + d->mNewAggregationButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); + g->addWidget( d->mNewAggregationButton, 0, 1 ); - connect( d->mNewAggregationButton, SIGNAL(clicked()), - SLOT(newAggregationButtonClicked()) ); + connect( d->mNewAggregationButton, SIGNAL(clicked()), + SLOT(newAggregationButtonClicked()) ); - d->mCloneAggregationButton = new QPushButton( i18n( "Clone Aggregation" ), base ); - d->mCloneAggregationButton->setIcon( KIcon( QLatin1String( "edit-copy" ) ) ); - d->mCloneAggregationButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); - g->addWidget( d->mCloneAggregationButton, 1, 1 ); + d->mCloneAggregationButton = new QPushButton( i18n( "Clone Aggregation" ), base ); + d->mCloneAggregationButton->setIcon( KIcon( QLatin1String( "edit-copy" ) ) ); + d->mCloneAggregationButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); + g->addWidget( d->mCloneAggregationButton, 1, 1 ); - connect( d->mCloneAggregationButton, SIGNAL(clicked()), - SLOT(cloneAggregationButtonClicked()) ); + connect( d->mCloneAggregationButton, SIGNAL(clicked()), + SLOT(cloneAggregationButtonClicked()) ); - QFrame * f = new QFrame( base ); - f->setFrameStyle( QFrame::Sunken | QFrame::HLine ); - f->setMinimumHeight( 24 ); - g->addWidget( f, 2, 1, Qt::AlignVCenter ); + QFrame * f = new QFrame( base ); + f->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + f->setMinimumHeight( 24 ); + g->addWidget( f, 2, 1, Qt::AlignVCenter ); - d->mExportAggregationButton = new QPushButton( i18n( "Export Aggregation..." ), base ); - g->addWidget( d->mExportAggregationButton, 3, 1 ); + d->mExportAggregationButton = new QPushButton( i18n( "Export Aggregation..." ), base ); + g->addWidget( d->mExportAggregationButton, 3, 1 ); - connect( d->mExportAggregationButton, SIGNAL(clicked()), - SLOT(exportAggregationButtonClicked()) ); + connect( d->mExportAggregationButton, SIGNAL(clicked()), + SLOT(exportAggregationButtonClicked()) ); - d->mImportAggregationButton = new QPushButton( i18n( "Import Aggregation..." ), base ); - g->addWidget( d->mImportAggregationButton, 4, 1 ); - connect( d->mImportAggregationButton, SIGNAL(clicked()), - SLOT(importAggregationButtonClicked()) ); + d->mImportAggregationButton = new QPushButton( i18n( "Import Aggregation..." ), base ); + g->addWidget( d->mImportAggregationButton, 4, 1 ); + connect( d->mImportAggregationButton, SIGNAL(clicked()), + SLOT(importAggregationButtonClicked()) ); - f = new QFrame( base ); - f->setFrameStyle( QFrame::Sunken | QFrame::HLine ); - f->setMinimumHeight( 24 ); - g->addWidget( f, 5, 1, Qt::AlignVCenter ); + f = new QFrame( base ); + f->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + f->setMinimumHeight( 24 ); + g->addWidget( f, 5, 1, Qt::AlignVCenter ); - d->mDeleteAggregationButton = new QPushButton( i18n( "Delete Aggregation" ), base ); - d->mDeleteAggregationButton->setIcon( KIcon( QLatin1String( "edit-delete" ) ) ); - d->mDeleteAggregationButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); - g->addWidget( d->mDeleteAggregationButton, 6, 1 ); + d->mDeleteAggregationButton = new QPushButton( i18n( "Delete Aggregation" ), base ); + d->mDeleteAggregationButton->setIcon( KIcon( QLatin1String( "edit-delete" ) ) ); + d->mDeleteAggregationButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); + g->addWidget( d->mDeleteAggregationButton, 6, 1 ); - connect( d->mDeleteAggregationButton, SIGNAL(clicked()), - SLOT(deleteAggregationButtonClicked()) ); + connect( d->mDeleteAggregationButton, SIGNAL(clicked()), + SLOT(deleteAggregationButtonClicked()) ); - d->mEditor = new AggregationEditor( base ); - g->addWidget( d->mEditor, 8, 0, 1, 2 ); + d->mEditor = new AggregationEditor( base ); + g->addWidget( d->mEditor, 8, 0, 1, 2 ); - connect( d->mEditor, SIGNAL(aggregationNameChanged()), - SLOT(editedAggregationNameChanged()) ); + connect( d->mEditor, SIGNAL(aggregationNameChanged()), + SLOT(editedAggregationNameChanged()) ); - g->setColumnStretch( 0, 1 ); - g->setRowStretch( 7, 1 ); + g->setColumnStretch( 0, 1 ); + g->setRowStretch( 7, 1 ); - connect( this, SIGNAL(okClicked()), - SLOT(okButtonClicked()) ); + connect( this, SIGNAL(okClicked()), + SLOT(okButtonClicked()) ); - d->fillAggregationList(); + d->fillAggregationList(); } ConfigureAggregationsDialog::~ConfigureAggregationsDialog() { - delete d; + delete d; } void ConfigureAggregationsDialog::selectAggregation( const QString &aggregationId ) { - AggregationListWidgetItem *item = d->findAggregationItemById( aggregationId ); - if ( item ) { - d->mAggregationList->setCurrentItem( item ); - d->aggregationListItemClicked(item); - } + AggregationListWidgetItem *item = d->findAggregationItemById( aggregationId ); + if ( item ) { + d->mAggregationList->setCurrentItem( item ); + d->aggregationListItemClicked(item); + } } void ConfigureAggregationsDialog::Private::okButtonClicked() { - commitEditor(); + commitEditor(); - Manager::instance()->removeAllAggregations(); + Manager::instance()->removeAllAggregations(); - const int c = mAggregationList->count(); - int i = 0; - while ( i < c ) - { - AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( mAggregationList->item( i ) ); - if ( item ) + const int c = mAggregationList->count(); + int i = 0; + while ( i < c ) { - Manager::instance()->addAggregation( item->aggregation() ); - item->forgetAggregation(); + AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( mAggregationList->item( i ) ); + if ( item ) + { + Manager::instance()->addAggregation( item->aggregation() ); + item->forgetAggregation(); + } + ++i; } - ++i; - } - Manager::instance()->aggregationsConfigurationCompleted(); + Manager::instance()->aggregationsConfigurationCompleted(); - q->close(); // this will delete too + q->close(); // this will delete too } void ConfigureAggregationsDialog::Private::commitEditor() { - Aggregation * editedAggregation = mEditor->editedAggregation(); - if ( !editedAggregation ) - return; - - mEditor->commit(); - - AggregationListWidgetItem * editedItem = findAggregationItemByAggregation( editedAggregation ); - if ( !editedItem ) - return; - const QString goodName = uniqueNameForAggregation( editedAggregation->name(), editedAggregation ); - editedAggregation->setName( goodName ); - editedItem->setText( goodName ); + Aggregation * editedAggregation = mEditor->editedAggregation(); + if ( !editedAggregation ) + return; + + mEditor->commit(); + + AggregationListWidgetItem * editedItem = findAggregationItemByAggregation( editedAggregation ); + if ( !editedItem ) + return; + const QString goodName = uniqueNameForAggregation( editedAggregation->name(), editedAggregation ); + editedAggregation->setName( goodName ); + editedItem->setText( goodName ); } void ConfigureAggregationsDialog::Private::editedAggregationNameChanged() { - Aggregation * set = mEditor->editedAggregation(); - if ( !set ) - return; + Aggregation * set = mEditor->editedAggregation(); + if ( !set ) + return; - AggregationListWidgetItem * it = findAggregationItemByAggregation( set ); - if ( !it ) - return; + AggregationListWidgetItem * it = findAggregationItemByAggregation( set ); + if ( !it ) + return; - const QString goodName = uniqueNameForAggregation( set->name(), set ); + const QString goodName = uniqueNameForAggregation( set->name(), set ); - it->setText( goodName ); + it->setText( goodName ); } void ConfigureAggregationsDialog::Private::fillAggregationList() { - const QHash< QString, Aggregation * > & sets = Manager::instance()->aggregations(); - QHash< QString, Aggregation * >::ConstIterator end( sets.constEnd() ); - for( QHash< QString, Aggregation * >::ConstIterator it = sets.constBegin(); it != end; ++it ) - (void)new AggregationListWidgetItem( mAggregationList, *( *it ) ); + const QHash< QString, Aggregation * > & sets = Manager::instance()->aggregations(); + QHash< QString, Aggregation * >::ConstIterator end( sets.constEnd() ); + for( QHash< QString, Aggregation * >::ConstIterator it = sets.constBegin(); it != end; ++it ) + (void)new AggregationListWidgetItem( mAggregationList, *( *it ) ); } void ConfigureAggregationsDialog::Private::aggregationListItemClicked(QListWidgetItem* cur) { - commitEditor(); - updateButton(cur); + commitEditor(); + updateButton(cur); } void ConfigureAggregationsDialog::Private::updateButton(QListWidgetItem* cur) { - const int numberOfSelectedItem(mAggregationList->selectedItems().count()); + const int numberOfSelectedItem(mAggregationList->selectedItems().count()); - AggregationListWidgetItem * item = cur ? dynamic_cast< AggregationListWidgetItem * >( cur ) : 0; - mDeleteAggregationButton->setEnabled( item && !item->aggregation()->readOnly() && ( mAggregationList->count() > 1 ) ); + AggregationListWidgetItem * item = cur ? dynamic_cast< AggregationListWidgetItem * >( cur ) : 0; + mDeleteAggregationButton->setEnabled( item && !item->aggregation()->readOnly() && ( mAggregationList->count() > 1 ) ); - mCloneAggregationButton->setEnabled( numberOfSelectedItem == 1 ); - mExportAggregationButton->setEnabled( numberOfSelectedItem > 0 ); - mEditor->editAggregation( item ? item->aggregation() : 0 ); - if ( item && !item->isSelected() ) - item->setSelected( true ); // make sure it's true + mCloneAggregationButton->setEnabled( numberOfSelectedItem == 1 ); + mExportAggregationButton->setEnabled( numberOfSelectedItem > 0 ); + mEditor->editAggregation( item ? item->aggregation() : 0 ); + if ( item && !item->isSelected() ) + item->setSelected( true ); // make sure it's true } AggregationListWidgetItem * ConfigureAggregationsDialog::Private::findAggregationItemByName( const QString &name, Aggregation * skipAggregation ) { - const int c = mAggregationList->count(); - int i = 0; - while ( i < c ) - { - AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( mAggregationList->item( i ) ); - if ( item ) + const int c = mAggregationList->count(); + int i = 0; + while ( i < c ) { - if ( item->aggregation() != skipAggregation ) - { - if ( item->aggregation()->name() == name ) - return item; - } - } - ++i; - } - return 0; + AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( mAggregationList->item( i ) ); + if ( item ) + { + if ( item->aggregation() != skipAggregation ) + { + if ( item->aggregation()->name() == name ) + return item; + } + } + ++i; + } + return 0; } AggregationListWidgetItem * ConfigureAggregationsDialog::Private::findAggregationItemById( const QString &aggregationId ) { - const int c = mAggregationList->count(); - int i = 0; - while ( i < c ) - { - AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( mAggregationList->item( i ) ); - if ( item ) + const int c = mAggregationList->count(); + int i = 0; + while ( i < c ) { - if ( item->aggregation()->id() == aggregationId ) - return item; + AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( mAggregationList->item( i ) ); + if ( item ) + { + if ( item->aggregation()->id() == aggregationId ) + return item; + } + ++i; } - ++i; - } - return 0; + return 0; } AggregationListWidgetItem * ConfigureAggregationsDialog::Private::findAggregationItemByAggregation( Aggregation * set ) { - const int c = mAggregationList->count(); - int i = 0; - while ( i < c ) - { - AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( mAggregationList->item( i ) ); - if ( item ) + const int c = mAggregationList->count(); + int i = 0; + while ( i < c ) { - if ( item->aggregation() == set ) - return item; + AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( mAggregationList->item( i ) ); + if ( item ) + { + if ( item->aggregation() == set ) + return item; + } + ++i; } - ++i; - } - return 0; + return 0; } QString ConfigureAggregationsDialog::Private::uniqueNameForAggregation( const QString& baseName, Aggregation * skipAggregation ) { - QString ret = baseName; - if( ret.isEmpty() ) - ret = i18n( "Unnamed Aggregation" ); - - int idx = 1; - - AggregationListWidgetItem * item = findAggregationItemByName( ret, skipAggregation ); - while ( item ) - { - idx++; - ret = QString::fromLatin1( "%1 %2" ).arg( baseName ).arg( idx ); - item = findAggregationItemByName( ret, skipAggregation ); - } - return ret; + QString ret = baseName; + if( ret.isEmpty() ) + ret = i18n( "Unnamed Aggregation" ); + + int idx = 1; + + AggregationListWidgetItem * item = findAggregationItemByName( ret, skipAggregation ); + while ( item ) + { + idx++; + ret = QString::fromLatin1( "%1 %2" ).arg( baseName ).arg( idx ); + item = findAggregationItemByName( ret, skipAggregation ); + } + return ret; } void ConfigureAggregationsDialog::Private::newAggregationButtonClicked() { - Aggregation emptyAggregation; - emptyAggregation.setName( uniqueNameForAggregation( i18n( "New Aggregation" ) ) ); - AggregationListWidgetItem * item = new AggregationListWidgetItem( mAggregationList, emptyAggregation ); + Aggregation emptyAggregation; + emptyAggregation.setName( uniqueNameForAggregation( i18n( "New Aggregation" ) ) ); + AggregationListWidgetItem * item = new AggregationListWidgetItem( mAggregationList, emptyAggregation ); - mAggregationList->setCurrentItem( item ); - mDeleteAggregationButton->setEnabled( item && !item->aggregation()->readOnly() ); + mAggregationList->setCurrentItem( item ); + mDeleteAggregationButton->setEnabled( item && !item->aggregation()->readOnly() ); } void ConfigureAggregationsDialog::Private::cloneAggregationButtonClicked() { - AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( mAggregationList->currentItem() ); - if ( !item ) - return; - commitEditor(); - item->setSelected(false); - Aggregation copyAggregation( *( item->aggregation() ) ); - copyAggregation.setReadOnly( false ); - copyAggregation.generateUniqueId(); // regenerate id so it becomes different - copyAggregation.setName( uniqueNameForAggregation( item->aggregation()->name() ) ); - item = new AggregationListWidgetItem( mAggregationList, copyAggregation ); + AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( mAggregationList->currentItem() ); + if ( !item ) + return; + commitEditor(); + item->setSelected(false); + Aggregation copyAggregation( *( item->aggregation() ) ); + copyAggregation.setReadOnly( false ); + copyAggregation.generateUniqueId(); // regenerate id so it becomes different + copyAggregation.setName( uniqueNameForAggregation( item->aggregation()->name() ) ); + item = new AggregationListWidgetItem( mAggregationList, copyAggregation ); - mAggregationList->setCurrentItem( item ); - aggregationListItemClicked( item ); + mAggregationList->setCurrentItem( item ); + aggregationListItemClicked( item ); } void ConfigureAggregationsDialog::Private::deleteAggregationButtonClicked() { - QList list = mAggregationList->selectedItems(); - if(list.isEmpty()) { - return; - } - - mEditor->editAggregation( 0 ); // forget it - Q_FOREACH(QListWidgetItem * it, list) { - AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( it ); - if ( !item ) - return; - if(!item->aggregation()->readOnly()) { - delete item; // this will trigger aggregationListCurrentItemChanged() - } - if ( mAggregationList->count() < 2 ) - break; // no way: desperately try to keep at least one option set alive :) - } + QList list = mAggregationList->selectedItems(); + if(list.isEmpty()) { + return; + } + + mEditor->editAggregation( 0 ); // forget it + Q_FOREACH(QListWidgetItem * it, list) { + AggregationListWidgetItem * item = dynamic_cast< AggregationListWidgetItem * >( it ); + if ( !item ) + return; + if(!item->aggregation()->readOnly()) { + delete item; // this will trigger aggregationListCurrentItemChanged() + } + if ( mAggregationList->count() < 2 ) + break; // no way: desperately try to keep at least one option set alive :) + } - AggregationListWidgetItem *newItem = dynamic_cast< AggregationListWidgetItem * >(mAggregationList->currentItem()); - updateButton(newItem); + AggregationListWidgetItem *newItem = dynamic_cast< AggregationListWidgetItem * >(mAggregationList->currentItem()); + updateButton(newItem); } void ConfigureAggregationsDialog::Private::importAggregationButtonClicked() { - const QString filename = KFileDialog::getOpenFileName(QString(),QString::fromLatin1("*"),q,i18n("Import Aggregation")); - if(!filename.isEmpty()) { - KConfig config(filename); - - if(config.hasGroup(QLatin1String("MessageListView::Aggregations"))) { - KConfigGroup grp( &config, QLatin1String("MessageListView::Aggregations") ); - const int cnt = grp.readEntry("Count",0); - int idx = 0; - while ( idx < cnt ) - { - const QString data = grp.readEntry( QString::fromLatin1( "Set%1" ).arg( idx ), QString() ); - if ( !data.isEmpty() ) - { - Aggregation * set = new Aggregation(); - if ( set->loadFromString( data ) ) - { - set->setReadOnly( false ); - set->generateUniqueId(); // regenerate id so it becomes different - set->setName( uniqueNameForAggregation( set->name() ) ); - (void)new AggregationListWidgetItem( mAggregationList, *set ); - } else { - delete set; // b0rken - } + const QString filename = KFileDialog::getOpenFileName(QString(),QString::fromLatin1("*"),q,i18n("Import Aggregation")); + if(!filename.isEmpty()) { + KConfig config(filename); + + if(config.hasGroup(QLatin1String("MessageListView::Aggregations"))) { + KConfigGroup grp( &config, QLatin1String("MessageListView::Aggregations") ); + const int cnt = grp.readEntry("Count",0); + int idx = 0; + while ( idx < cnt ) + { + const QString data = grp.readEntry( QString::fromLatin1( "Set%1" ).arg( idx ), QString() ); + if ( !data.isEmpty() ) + { + Aggregation * set = new Aggregation(); + if ( set->loadFromString( data ) ) + { + set->setReadOnly( false ); + set->generateUniqueId(); // regenerate id so it becomes different + set->setName( uniqueNameForAggregation( set->name() ) ); + (void)new AggregationListWidgetItem( mAggregationList, *set ); + } else { + delete set; // b0rken + } + } + ++idx; + } } - ++idx; - } } - } } void ConfigureAggregationsDialog::Private::exportAggregationButtonClicked() { - QList list = mAggregationList->selectedItems(); - if(list.isEmpty()) { - return; - } - const QString filename = KFileDialog::getSaveFileName(QString(),QString::fromLatin1("*"),q,i18n("Export Aggregation")); - if(!filename.isEmpty()) { - KConfig config(filename); - - KConfigGroup grp( &config, QLatin1String("MessageListView::Aggregations") ); - grp.writeEntry( "Count", list.count() ); - - int idx = 0; - Q_FOREACH(QListWidgetItem *item, list) { - AggregationListWidgetItem * themeItem = static_cast< AggregationListWidgetItem * >( item ); - grp.writeEntry( QString::fromLatin1( "Set%1" ).arg( idx ), themeItem->aggregation()->saveToString() ); - ++idx; + QList list = mAggregationList->selectedItems(); + if(list.isEmpty()) { + return; + } + const QString filename = KFileDialog::getSaveFileName(QString(),QString::fromLatin1("*"),q,i18n("Export Aggregation")); + if(!filename.isEmpty()) { + KConfig config(filename); + + KConfigGroup grp( &config, QLatin1String("MessageListView::Aggregations") ); + grp.writeEntry( "Count", list.count() ); + + int idx = 0; + Q_FOREACH(QListWidgetItem *item, list) { + AggregationListWidgetItem * themeItem = static_cast< AggregationListWidgetItem * >( item ); + grp.writeEntry( QString::fromLatin1( "Set%1" ).arg( idx ), themeItem->aggregation()->saveToString() ); + ++idx; + } } - } } diff -Nru kdepim-4.12.97/messagelist/utils/configureaggregationsdialog.h kdepim-4.13.0/messagelist/utils/configureaggregationsdialog.h --- kdepim-4.12.97/messagelist/utils/configureaggregationsdialog.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/configureaggregationsdialog.h 2014-04-10 07:40:20.000000000 +0000 @@ -50,26 +50,26 @@ */ class MESSAGELIST_EXPORT ConfigureAggregationsDialog : public KDialog { - Q_OBJECT + Q_OBJECT public: - explicit ConfigureAggregationsDialog( QWidget *parent = 0 ); - ~ConfigureAggregationsDialog(); + explicit ConfigureAggregationsDialog( QWidget *parent = 0 ); + ~ConfigureAggregationsDialog(); - void selectAggregation( const QString &aggregationId ); + void selectAggregation( const QString &aggregationId ); private: - Q_PRIVATE_SLOT(d, void aggregationListItemClicked(QListWidgetItem* cur)) - Q_PRIVATE_SLOT(d, void newAggregationButtonClicked()) - Q_PRIVATE_SLOT(d, void cloneAggregationButtonClicked()) - Q_PRIVATE_SLOT(d, void deleteAggregationButtonClicked()) - Q_PRIVATE_SLOT(d, void editedAggregationNameChanged()) - Q_PRIVATE_SLOT(d, void okButtonClicked()) - Q_PRIVATE_SLOT(d, void importAggregationButtonClicked()) - Q_PRIVATE_SLOT(d, void exportAggregationButtonClicked()) + Q_PRIVATE_SLOT(d, void aggregationListItemClicked(QListWidgetItem* cur)) + Q_PRIVATE_SLOT(d, void newAggregationButtonClicked()) + Q_PRIVATE_SLOT(d, void cloneAggregationButtonClicked()) + Q_PRIVATE_SLOT(d, void deleteAggregationButtonClicked()) + Q_PRIVATE_SLOT(d, void editedAggregationNameChanged()) + Q_PRIVATE_SLOT(d, void okButtonClicked()) + Q_PRIVATE_SLOT(d, void importAggregationButtonClicked()) + Q_PRIVATE_SLOT(d, void exportAggregationButtonClicked()) - class Private; - Private * const d; + class Private; + Private * const d; }; } // namespace Utils diff -Nru kdepim-4.12.97/messagelist/utils/configurethemesdialog.cpp kdepim-4.13.0/messagelist/utils/configurethemesdialog.cpp --- kdepim-4.12.97/messagelist/utils/configurethemesdialog.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/configurethemesdialog.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -46,37 +46,37 @@ class ThemeListWidgetItem : public QListWidgetItem { public: - ThemeListWidgetItem( QListWidget * par, const Core::Theme &set ) - : QListWidgetItem( set.name(), par ) - { - mTheme = new Core::Theme( set ); - } - ~ThemeListWidgetItem() - { - delete mTheme; - } - - Core::Theme * theme() const - { - return mTheme; - } - void forgetTheme() - { - mTheme = 0; - } + ThemeListWidgetItem( QListWidget * par, const Core::Theme &set ) + : QListWidgetItem( set.name(), par ) + { + mTheme = new Core::Theme( set ); + } + ~ThemeListWidgetItem() + { + delete mTheme; + } + + Core::Theme * theme() const + { + return mTheme; + } + void forgetTheme() + { + mTheme = 0; + } private: - Core::Theme * mTheme; + Core::Theme * mTheme; }; class ThemeListWidget : public QListWidget { public: - ThemeListWidget( QWidget * parent ) - : QListWidget( parent ) + ThemeListWidget( QWidget * parent ) + : QListWidget( parent ) {} public: - // need a larger but shorter QListWidget - QSize sizeHint() const + // need a larger but shorter QListWidget + QSize sizeHint() const { return QSize( 450, 128 ); } }; @@ -88,384 +88,384 @@ using namespace MessageList::Utils; ConfigureThemesDialog::ConfigureThemesDialog( QWidget *parent ) - : KDialog( parent ), d( new Private( this ) ) + : KDialog( parent ), d( new Private( this ) ) { - setAttribute( Qt::WA_DeleteOnClose ); - setWindowModality( Qt::ApplicationModal ); // FIXME: Sure ? - setButtons( Ok | Cancel ); - setWindowTitle( i18n( "Customize Themes" ) ); + setAttribute( Qt::WA_DeleteOnClose ); + setWindowModality( Qt::ApplicationModal ); // FIXME: Sure ? + setButtons( Ok | Cancel ); + setWindowTitle( i18n( "Customize Themes" ) ); - QWidget * base = new QWidget( this ); - setMainWidget( base ); + QWidget * base = new QWidget( this ); + setMainWidget( base ); - QGridLayout * g = new QGridLayout( base ); - g->setContentsMargins( 0, 0, 0, 0 ); + QGridLayout * g = new QGridLayout( base ); + g->setContentsMargins( 0, 0, 0, 0 ); - d->mThemeList = new ThemeListWidget( base ); - d->mThemeList->setSelectionMode(QAbstractItemView::ExtendedSelection); - d->mThemeList->setSortingEnabled( true ); - g->addWidget( d->mThemeList, 0, 0, 7, 1 ); + d->mThemeList = new ThemeListWidget( base ); + d->mThemeList->setSelectionMode(QAbstractItemView::ExtendedSelection); + d->mThemeList->setSortingEnabled( true ); + g->addWidget( d->mThemeList, 0, 0, 7, 1 ); - connect( d->mThemeList, SIGNAL(itemClicked(QListWidgetItem*)), - SLOT(themeListItemClicked(QListWidgetItem*)) ); + connect( d->mThemeList, SIGNAL(itemClicked(QListWidgetItem*)), + SLOT(themeListItemClicked(QListWidgetItem*)) ); - d->mNewThemeButton = new QPushButton( i18n( "New Theme" ), base ); - d->mNewThemeButton->setIcon( KIcon( QLatin1String( "document-new" ) ) ); - d->mNewThemeButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); - g->addWidget( d->mNewThemeButton, 0, 1 ); + d->mNewThemeButton = new QPushButton( i18n( "New Theme" ), base ); + d->mNewThemeButton->setIcon( KIcon( QLatin1String( "document-new" ) ) ); + d->mNewThemeButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); + g->addWidget( d->mNewThemeButton, 0, 1 ); - connect( d->mNewThemeButton, SIGNAL(clicked()), - SLOT(newThemeButtonClicked()) ); + connect( d->mNewThemeButton, SIGNAL(clicked()), + SLOT(newThemeButtonClicked()) ); - d->mCloneThemeButton = new QPushButton( i18n( "Clone Theme" ), base ); - d->mCloneThemeButton->setIcon( KIcon( QLatin1String( "edit-copy" ) ) ); - d->mCloneThemeButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); - g->addWidget( d->mCloneThemeButton, 1, 1 ); + d->mCloneThemeButton = new QPushButton( i18n( "Clone Theme" ), base ); + d->mCloneThemeButton->setIcon( KIcon( QLatin1String( "edit-copy" ) ) ); + d->mCloneThemeButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); + g->addWidget( d->mCloneThemeButton, 1, 1 ); - connect( d->mCloneThemeButton, SIGNAL(clicked()), - SLOT(cloneThemeButtonClicked()) ); + connect( d->mCloneThemeButton, SIGNAL(clicked()), + SLOT(cloneThemeButtonClicked()) ); - QFrame * f = new QFrame( base ); - f->setFrameStyle( QFrame::Sunken | QFrame::HLine ); - f->setMinimumHeight( 24 ); - g->addWidget( f, 2, 1, Qt::AlignVCenter ); + QFrame * f = new QFrame( base ); + f->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + f->setMinimumHeight( 24 ); + g->addWidget( f, 2, 1, Qt::AlignVCenter ); - d->mExportThemeButton = new QPushButton( i18n( "Export Theme..." ), base ); - g->addWidget( d->mExportThemeButton, 3, 1 ); + d->mExportThemeButton = new QPushButton( i18n( "Export Theme..." ), base ); + g->addWidget( d->mExportThemeButton, 3, 1 ); - connect( d->mExportThemeButton, SIGNAL(clicked()), - SLOT(exportThemeButtonClicked()) ); + connect( d->mExportThemeButton, SIGNAL(clicked()), + SLOT(exportThemeButtonClicked()) ); - d->mImportThemeButton = new QPushButton( i18n( "Import Theme..." ), base ); - g->addWidget( d->mImportThemeButton, 4, 1 ); - connect( d->mImportThemeButton, SIGNAL(clicked()), - SLOT(importThemeButtonClicked()) ); + d->mImportThemeButton = new QPushButton( i18n( "Import Theme..." ), base ); + g->addWidget( d->mImportThemeButton, 4, 1 ); + connect( d->mImportThemeButton, SIGNAL(clicked()), + SLOT(importThemeButtonClicked()) ); - f = new QFrame( base ); - f->setFrameStyle( QFrame::Sunken | QFrame::HLine ); - f->setMinimumHeight( 24 ); - g->addWidget( f, 5, 1, Qt::AlignVCenter ); + f = new QFrame( base ); + f->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + f->setMinimumHeight( 24 ); + g->addWidget( f, 5, 1, Qt::AlignVCenter ); - d->mDeleteThemeButton = new QPushButton( i18n( "Delete Theme" ), base ); - d->mDeleteThemeButton->setIcon( KIcon( QLatin1String( "edit-delete" ) ) ); - d->mDeleteThemeButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); - g->addWidget( d->mDeleteThemeButton, 6, 1 ); + d->mDeleteThemeButton = new QPushButton( i18n( "Delete Theme" ), base ); + d->mDeleteThemeButton->setIcon( KIcon( QLatin1String( "edit-delete" ) ) ); + d->mDeleteThemeButton->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) ); + g->addWidget( d->mDeleteThemeButton, 6, 1 ); - connect( d->mDeleteThemeButton, SIGNAL(clicked()), - SLOT(deleteThemeButtonClicked()) ); + connect( d->mDeleteThemeButton, SIGNAL(clicked()), + SLOT(deleteThemeButtonClicked()) ); - d->mEditor = new ThemeEditor( base ); - g->addWidget( d->mEditor, 8, 0, 1, 2 ); + d->mEditor = new ThemeEditor( base ); + g->addWidget( d->mEditor, 8, 0, 1, 2 ); - connect( d->mEditor, SIGNAL(themeNameChanged()), - SLOT(editedThemeNameChanged()) ); + connect( d->mEditor, SIGNAL(themeNameChanged()), + SLOT(editedThemeNameChanged()) ); - g->setColumnStretch( 0, 1 ); - g->setRowStretch( 4, 1 ); + g->setColumnStretch( 0, 1 ); + g->setRowStretch( 4, 1 ); - connect( this, SIGNAL(okClicked()), - SLOT(okButtonClicked()) ); + connect( this, SIGNAL(okClicked()), + SLOT(okButtonClicked()) ); - d->fillThemeList(); + d->fillThemeList(); } ConfigureThemesDialog::~ConfigureThemesDialog() { - delete d; + delete d; } void ConfigureThemesDialog::selectTheme( const QString &themeId ) { - ThemeListWidgetItem * item = d->findThemeItemById( themeId ); - if ( item ) { - d->mThemeList->setCurrentItem( item ); - d->themeListItemClicked(item); - } + ThemeListWidgetItem * item = d->findThemeItemById( themeId ); + if ( item ) { + d->mThemeList->setCurrentItem( item ); + d->themeListItemClicked(item); + } } void ConfigureThemesDialog::Private::okButtonClicked() { - commitEditor(); + commitEditor(); - Manager::instance()->removeAllThemes(); + Manager::instance()->removeAllThemes(); - const int c = mThemeList->count(); - int i = 0; - while ( i < c ) - { - ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( mThemeList->item( i ) ); - if ( item ) + const int c = mThemeList->count(); + int i = 0; + while ( i < c ) { - Manager::instance()->addTheme( item->theme() ); - item->forgetTheme(); + ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( mThemeList->item( i ) ); + if ( item ) + { + Manager::instance()->addTheme( item->theme() ); + item->forgetTheme(); + } + ++i; } - ++i; - } - Manager::instance()->themesConfigurationCompleted(); + Manager::instance()->themesConfigurationCompleted(); - q->close(); // this will delete too + q->close(); // this will delete too } void ConfigureThemesDialog::Private::commitEditor() { - Theme * editedTheme = mEditor->editedTheme(); - if ( !editedTheme ) - return; - - mEditor->commit(); - - ThemeListWidgetItem * editedItem = findThemeItemByTheme( editedTheme ); - if ( !editedItem ) - return; - - // We must reset the runtime column state as the columns might have - // totally changed in the editor - editedTheme->resetColumnState(); - - QString goodName = uniqueNameForTheme( editedTheme->name(), editedTheme ); - editedTheme->setName( goodName ); - editedItem->setText( goodName ); + Theme * editedTheme = mEditor->editedTheme(); + if ( !editedTheme ) + return; + + mEditor->commit(); + + ThemeListWidgetItem * editedItem = findThemeItemByTheme( editedTheme ); + if ( !editedItem ) + return; + + // We must reset the runtime column state as the columns might have + // totally changed in the editor + editedTheme->resetColumnState(); + + QString goodName = uniqueNameForTheme( editedTheme->name(), editedTheme ); + editedTheme->setName( goodName ); + editedItem->setText( goodName ); } void ConfigureThemesDialog::Private::editedThemeNameChanged() { - Theme * set = mEditor->editedTheme(); - if ( !set ) - return; + Theme * set = mEditor->editedTheme(); + if ( !set ) + return; - ThemeListWidgetItem * it = findThemeItemByTheme( set ); - if ( !it ) - return; + ThemeListWidgetItem * it = findThemeItemByTheme( set ); + if ( !it ) + return; - QString goodName = uniqueNameForTheme( set->name(), set ); + QString goodName = uniqueNameForTheme( set->name(), set ); - it->setText( goodName ); + it->setText( goodName ); } void ConfigureThemesDialog::Private::fillThemeList() { - const QHash< QString, Theme * >& sets = Manager::instance()->themes(); + const QHash< QString, Theme * >& sets = Manager::instance()->themes(); - QHash< QString, Theme * >::ConstIterator end( sets.constEnd() ); - for( QHash< QString, Theme * >::ConstIterator it = sets.constBegin(); it != end; ++it ) - (void)new ThemeListWidgetItem( mThemeList, *( *it ) ); + QHash< QString, Theme * >::ConstIterator end( sets.constEnd() ); + for( QHash< QString, Theme * >::ConstIterator it = sets.constBegin(); it != end; ++it ) + (void)new ThemeListWidgetItem( mThemeList, *( *it ) ); } void ConfigureThemesDialog::Private::themeListItemClicked(QListWidgetItem* cur) { - commitEditor(); + commitEditor(); - const int numberOfSelectedItem(mThemeList->selectedItems().count()); + const int numberOfSelectedItem(mThemeList->selectedItems().count()); - ThemeListWidgetItem * item = cur ? dynamic_cast< ThemeListWidgetItem * >( cur ) : 0; - mDeleteThemeButton->setEnabled( item && !item->theme()->readOnly() ); - mCloneThemeButton->setEnabled( numberOfSelectedItem == 1 ); - mEditor->editTheme( item ? item->theme() : 0 ); - mExportThemeButton->setEnabled( numberOfSelectedItem > 0 ); + ThemeListWidgetItem * item = cur ? dynamic_cast< ThemeListWidgetItem * >( cur ) : 0; + mDeleteThemeButton->setEnabled( item && !item->theme()->readOnly() ); + mCloneThemeButton->setEnabled( numberOfSelectedItem == 1 ); + mEditor->editTheme( item ? item->theme() : 0 ); + mExportThemeButton->setEnabled( numberOfSelectedItem > 0 ); - if ( item && !item->isSelected() ) - item->setSelected( true ); // make sure it's true + if ( item && !item->isSelected() ) + item->setSelected( true ); // make sure it's true } ThemeListWidgetItem * ConfigureThemesDialog::Private::findThemeItemById( const QString &themeId ) { - const int c = mThemeList->count(); - int i = 0; - while ( i < c ) - { - ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( mThemeList->item( i ) ); - if ( item ) + const int c = mThemeList->count(); + int i = 0; + while ( i < c ) { - if ( item->theme()->id() == themeId ) - return item; + ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( mThemeList->item( i ) ); + if ( item ) + { + if ( item->theme()->id() == themeId ) + return item; + } + ++i; } - ++i; - } - return 0; + return 0; } ThemeListWidgetItem * ConfigureThemesDialog::Private::findThemeItemByName( const QString &name, Theme * skipTheme ) { - const int c = mThemeList->count(); - int i = 0; - while ( i < c ) - { - ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( mThemeList->item( i ) ); - if ( item ) + const int c = mThemeList->count(); + int i = 0; + while ( i < c ) { - if ( item->theme() != skipTheme ) - { - if ( item->theme()->name() == name ) - return item; - } - } - ++i; - } - return 0; + ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( mThemeList->item( i ) ); + if ( item ) + { + if ( item->theme() != skipTheme ) + { + if ( item->theme()->name() == name ) + return item; + } + } + ++i; + } + return 0; } ThemeListWidgetItem * ConfigureThemesDialog::Private::findThemeItemByTheme( Theme * set ) { - const int c = mThemeList->count(); - int i = 0; - while ( i < c ) - { - ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( mThemeList->item( i ) ); - if ( item ) + const int c = mThemeList->count(); + int i = 0; + while ( i < c ) { - if ( item->theme() == set ) - return item; + ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( mThemeList->item( i ) ); + if ( item ) + { + if ( item->theme() == set ) + return item; + } + ++i; } - ++i; - } - return 0; + return 0; } QString ConfigureThemesDialog::Private::uniqueNameForTheme( const QString& baseName, Theme * skipTheme ) { - QString ret = baseName; - if( ret.isEmpty() ) - ret = i18n( "Unnamed Theme" ); - - int idx = 1; - - ThemeListWidgetItem * item = findThemeItemByName( ret, skipTheme ); - while ( item ) - { - idx++; - ret = QString::fromLatin1( "%1 %2" ).arg( baseName ).arg( idx ); - item = findThemeItemByName( ret, skipTheme ); - } - return ret; + QString ret = baseName; + if( ret.isEmpty() ) + ret = i18n( "Unnamed Theme" ); + + int idx = 1; + + ThemeListWidgetItem * item = findThemeItemByName( ret, skipTheme ); + while ( item ) + { + idx++; + ret = QString::fromLatin1( "%1 %2" ).arg( baseName ).arg( idx ); + item = findThemeItemByName( ret, skipTheme ); + } + return ret; } void ConfigureThemesDialog::Private::newThemeButtonClicked() { - const int numberOfSelectedItem(mThemeList->selectedItems().count()); - Theme emptyTheme; - emptyTheme.setName( uniqueNameForTheme( i18n( "New Theme" ) ) ); - Theme::Column * col = new Theme::Column(); - col->setLabel( i18n( "New Column" ) ); - col->setVisibleByDefault( true ); - col->addMessageRow( new Theme::Row() ); - col->addGroupHeaderRow( new Theme::Row() ); - emptyTheme.addColumn( col ); - ThemeListWidgetItem * item = new ThemeListWidgetItem( mThemeList, emptyTheme ); - - mThemeList->setCurrentItem( item ); - mEditor->editTheme( item->theme() ); - - mDeleteThemeButton->setEnabled( !item->theme()->readOnly() ); - mExportThemeButton->setEnabled( item ); - mCloneThemeButton->setEnabled(numberOfSelectedItem == 1); + const int numberOfSelectedItem(mThemeList->selectedItems().count()); + Theme emptyTheme; + emptyTheme.setName( uniqueNameForTheme( i18n( "New Theme" ) ) ); + Theme::Column * col = new Theme::Column(); + col->setLabel( i18n( "New Column" ) ); + col->setVisibleByDefault( true ); + col->addMessageRow( new Theme::Row() ); + col->addGroupHeaderRow( new Theme::Row() ); + emptyTheme.addColumn( col ); + ThemeListWidgetItem * item = new ThemeListWidgetItem( mThemeList, emptyTheme ); + + mThemeList->setCurrentItem( item ); + mEditor->editTheme( item->theme() ); + + mDeleteThemeButton->setEnabled( !item->theme()->readOnly() ); + mExportThemeButton->setEnabled( item ); + mCloneThemeButton->setEnabled(numberOfSelectedItem == 1); } void ConfigureThemesDialog::Private::cloneThemeButtonClicked() { - ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( mThemeList->currentItem() ); - if ( !item ) - return; - commitEditor(); - item->setSelected(false); - Theme copyTheme( *( item->theme() ) ); - copyTheme.setReadOnly( false ); - copyTheme.detach(); // detach shared data - copyTheme.generateUniqueId(); // regenerate id so it becomes different - copyTheme.setName( uniqueNameForTheme( item->theme()->name() ) ); - item = new ThemeListWidgetItem( mThemeList, copyTheme ); - - mThemeList->setCurrentItem( item ); - mEditor->editTheme( item->theme() ); - - const int numberOfSelectedItem(mThemeList->selectedItems().count()); - mDeleteThemeButton->setEnabled( !item->theme()->readOnly() ); - mExportThemeButton->setEnabled( true ); - mCloneThemeButton->setEnabled(numberOfSelectedItem == 1); + ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( mThemeList->currentItem() ); + if ( !item ) + return; + commitEditor(); + item->setSelected(false); + Theme copyTheme( *( item->theme() ) ); + copyTheme.setReadOnly( false ); + copyTheme.detach(); // detach shared data + copyTheme.generateUniqueId(); // regenerate id so it becomes different + copyTheme.setName( uniqueNameForTheme( item->theme()->name() ) ); + item = new ThemeListWidgetItem( mThemeList, copyTheme ); + + mThemeList->setCurrentItem( item ); + mEditor->editTheme( item->theme() ); + + const int numberOfSelectedItem(mThemeList->selectedItems().count()); + mDeleteThemeButton->setEnabled( !item->theme()->readOnly() ); + mExportThemeButton->setEnabled( true ); + mCloneThemeButton->setEnabled(numberOfSelectedItem == 1); } void ConfigureThemesDialog::Private::deleteThemeButtonClicked() { - QList list = mThemeList->selectedItems(); - if(list.isEmpty()) { - return; - } - - mEditor->editTheme( 0 ); // forget it - Q_FOREACH(QListWidgetItem * it, list) { - ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( it ); - if ( !item ) - return; - if(!item->theme()->readOnly()) { - delete item;// this will trigger themeListCurrentItemChanged() - } - if ( mThemeList->count() < 2 ) - break; // no way: desperately try to keep at least one option set alive :) - } - - ThemeListWidgetItem *newItem = dynamic_cast< ThemeListWidgetItem * >(mThemeList->currentItem()); - mDeleteThemeButton->setEnabled( newItem && !newItem->theme()->readOnly() ); - mExportThemeButton->setEnabled( newItem ); - const int numberOfSelectedItem(mThemeList->selectedItems().count()); - mCloneThemeButton->setEnabled(numberOfSelectedItem == 1); + QList list = mThemeList->selectedItems(); + if(list.isEmpty()) { + return; + } + + mEditor->editTheme( 0 ); // forget it + Q_FOREACH(QListWidgetItem * it, list) { + ThemeListWidgetItem * item = dynamic_cast< ThemeListWidgetItem * >( it ); + if ( !item ) + return; + if(!item->theme()->readOnly()) { + delete item;// this will trigger themeListCurrentItemChanged() + } + if ( mThemeList->count() < 2 ) + break; // no way: desperately try to keep at least one option set alive :) + } + + ThemeListWidgetItem *newItem = dynamic_cast< ThemeListWidgetItem * >(mThemeList->currentItem()); + mDeleteThemeButton->setEnabled( newItem && !newItem->theme()->readOnly() ); + mExportThemeButton->setEnabled( newItem ); + const int numberOfSelectedItem(mThemeList->selectedItems().count()); + mCloneThemeButton->setEnabled(numberOfSelectedItem == 1); } void ConfigureThemesDialog::Private::importThemeButtonClicked() { - const QString filename = KFileDialog::getOpenFileName(QString(),QString::fromLatin1("*"),q,i18n("Import Theme")); - if(!filename.isEmpty()) { - KConfig config(filename); - - if(config.hasGroup(QLatin1String("MessageListView::Themes"))) { - KConfigGroup grp( &config, QLatin1String("MessageListView::Themes") ); - const int cnt = grp.readEntry( "Count", 0 ); - int idx = 0; - while ( idx < cnt ) { - const QString data = grp.readEntry( QString::fromLatin1( "Set%1" ).arg( idx ), QString() ); - if ( !data.isEmpty() ) - { - Theme * set = new Theme(); - if ( set->loadFromString( data ) ) { - set->setReadOnly( false ); - set->detach(); // detach shared data - set->generateUniqueId(); // regenerate id so it becomes different - set->setName( uniqueNameForTheme( set->name() ) ); - (void)new ThemeListWidgetItem( mThemeList, *set ); - } else { - delete set; - } + const QString filename = KFileDialog::getOpenFileName(QString(),QString::fromLatin1("*"),q,i18n("Import Theme")); + if(!filename.isEmpty()) { + KConfig config(filename); + + if(config.hasGroup(QLatin1String("MessageListView::Themes"))) { + KConfigGroup grp( &config, QLatin1String("MessageListView::Themes") ); + const int cnt = grp.readEntry( "Count", 0 ); + int idx = 0; + while ( idx < cnt ) { + const QString data = grp.readEntry( QString::fromLatin1( "Set%1" ).arg( idx ), QString() ); + if ( !data.isEmpty() ) + { + Theme * set = new Theme(); + if ( set->loadFromString( data ) ) { + set->setReadOnly( false ); + set->detach(); // detach shared data + set->generateUniqueId(); // regenerate id so it becomes different + set->setName( uniqueNameForTheme( set->name() ) ); + (void)new ThemeListWidgetItem( mThemeList, *set ); + } else { + delete set; + } + } + ++idx; + } } - ++idx; - } } - } } void ConfigureThemesDialog::Private::exportThemeButtonClicked() { - QList list = mThemeList->selectedItems(); - if(list.isEmpty()) { - return; - } - const QString filename = KFileDialog::getSaveFileName(QString(),QString::fromLatin1("*"),q,i18n("Export Theme")); - if(!filename.isEmpty()) { - KConfig config(filename); - - KConfigGroup grp( &config, QLatin1String("MessageListView::Themes") ); - grp.writeEntry( "Count", list.count() ); - - int idx = 0; - Q_FOREACH(QListWidgetItem *item, list) { - ThemeListWidgetItem * themeItem = static_cast< ThemeListWidgetItem * >( item ); - grp.writeEntry( QString::fromLatin1( "Set%1" ).arg( idx ), themeItem->theme()->saveToString() ); - ++idx; - } - } + QList list = mThemeList->selectedItems(); + if(list.isEmpty()) { + return; + } + const QString filename = KFileDialog::getSaveFileName(QString(),QString::fromLatin1("*"),q,i18n("Export Theme")); + if(!filename.isEmpty()) { + KConfig config(filename); + + KConfigGroup grp( &config, QLatin1String("MessageListView::Themes") ); + grp.writeEntry( "Count", list.count() ); + + int idx = 0; + Q_FOREACH(QListWidgetItem *item, list) { + ThemeListWidgetItem * themeItem = static_cast< ThemeListWidgetItem * >( item ); + grp.writeEntry( QString::fromLatin1( "Set%1" ).arg( idx ), themeItem->theme()->saveToString() ); + ++idx; + } + } } diff -Nru kdepim-4.12.97/messagelist/utils/configurethemesdialog.h kdepim-4.13.0/messagelist/utils/configurethemesdialog.h --- kdepim-4.12.97/messagelist/utils/configurethemesdialog.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/configurethemesdialog.h 2014-04-10 07:40:20.000000000 +0000 @@ -44,27 +44,27 @@ class MESSAGELIST_EXPORT ConfigureThemesDialog : public KDialog { - Q_OBJECT + Q_OBJECT public: - explicit ConfigureThemesDialog( QWidget *parent = 0 ); - ~ConfigureThemesDialog(); + explicit ConfigureThemesDialog( QWidget *parent = 0 ); + ~ConfigureThemesDialog(); - void selectTheme( const QString &themeId ); + void selectTheme( const QString &themeId ); private: - Q_PRIVATE_SLOT(d, void themeListItemClicked(QListWidgetItem*)) - Q_PRIVATE_SLOT(d, void newThemeButtonClicked()) - Q_PRIVATE_SLOT(d, void cloneThemeButtonClicked()) - Q_PRIVATE_SLOT(d, void deleteThemeButtonClicked()) - Q_PRIVATE_SLOT(d, void editedThemeNameChanged()) - Q_PRIVATE_SLOT(d, void okButtonClicked()) - Q_PRIVATE_SLOT(d, void importThemeButtonClicked()) - Q_PRIVATE_SLOT(d, void exportThemeButtonClicked()) + Q_PRIVATE_SLOT(d, void themeListItemClicked(QListWidgetItem*)) + Q_PRIVATE_SLOT(d, void newThemeButtonClicked()) + Q_PRIVATE_SLOT(d, void cloneThemeButtonClicked()) + Q_PRIVATE_SLOT(d, void deleteThemeButtonClicked()) + Q_PRIVATE_SLOT(d, void editedThemeNameChanged()) + Q_PRIVATE_SLOT(d, void okButtonClicked()) + Q_PRIVATE_SLOT(d, void importThemeButtonClicked()) + Q_PRIVATE_SLOT(d, void exportThemeButtonClicked()) - class Private; - Private * const d; + class Private; + Private * const d; }; } // namespace Utils diff -Nru kdepim-4.12.97/messagelist/utils/optionseteditor.cpp kdepim-4.13.0/messagelist/utils/optionseteditor.cpp --- kdepim-4.12.97/messagelist/utils/optionseteditor.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/optionseteditor.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -33,33 +33,33 @@ using namespace MessageList::Core; OptionSetEditor::OptionSetEditor( QWidget *parent ) - : KTabWidget( parent ) + : KTabWidget( parent ) { - // General tab - QWidget * tab = new QWidget( this ); - addTab( tab, i18nc( "@title:tab General options of a view mode", "General" ) ); + // General tab + QWidget * tab = new QWidget( this ); + addTab( tab, i18nc( "@title:tab General options of a view mode", "General" ) ); - QGridLayout * tabg = new QGridLayout( tab ); + QGridLayout * tabg = new QGridLayout( tab ); - QLabel * l = new QLabel( i18nc( "@label:textbox Name of the option", "Name:" ), tab ); - tabg->addWidget( l, 0, 0 ); + QLabel * l = new QLabel( i18nc( "@label:textbox Name of the option", "Name:" ), tab ); + tabg->addWidget( l, 0, 0 ); - mNameEdit = new KLineEdit( tab ); + mNameEdit = new KLineEdit( tab ); - tabg->addWidget( mNameEdit, 0, 1 ); + tabg->addWidget( mNameEdit, 0, 1 ); - connect( mNameEdit, SIGNAL(textEdited(QString)), - SLOT(slotNameEditTextEdited(QString)) ); + connect( mNameEdit, SIGNAL(textEdited(QString)), + SLOT(slotNameEditTextEdited(QString)) ); - l = new QLabel( i18nc( "@label:textbox Description of the option", "Description:" ), tab ); - tabg->addWidget( l, 1, 0 ); + l = new QLabel( i18nc( "@label:textbox Description of the option", "Description:" ), tab ); + tabg->addWidget( l, 1, 0 ); - mDescriptionEdit = new KTextEdit( tab ); - mDescriptionEdit->setAcceptRichText(false); - tabg->addWidget( mDescriptionEdit, 1, 1, 2, 1 ); + mDescriptionEdit = new KTextEdit( tab ); + mDescriptionEdit->setAcceptRichText(false); + tabg->addWidget( mDescriptionEdit, 1, 1, 2, 1 ); - tabg->setColumnStretch( 1, 1 ); - tabg->setRowStretch( 2, 1 ); + tabg->setColumnStretch( 1, 1 ); + tabg->setRowStretch( 2, 1 ); } @@ -69,18 +69,18 @@ void OptionSetEditor::setReadOnly( bool readOnly ) { - mDescriptionEdit->setReadOnly( readOnly ); - mNameEdit->setReadOnly( readOnly ); + mDescriptionEdit->setReadOnly( readOnly ); + mNameEdit->setReadOnly( readOnly ); } KTextEdit *OptionSetEditor::descriptionEdit() const { - return mDescriptionEdit; + return mDescriptionEdit; } KLineEdit * OptionSetEditor::nameEdit() const { - return mNameEdit; + return mNameEdit; } diff -Nru kdepim-4.12.97/messagelist/utils/optionseteditor.h kdepim-4.13.0/messagelist/utils/optionseteditor.h --- kdepim-4.12.97/messagelist/utils/optionseteditor.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/optionseteditor.h 2014-04-10 07:40:20.000000000 +0000 @@ -44,37 +44,37 @@ */ class OptionSetEditor : public KTabWidget { - Q_OBJECT + Q_OBJECT public: - explicit OptionSetEditor( QWidget *parent ); - ~OptionSetEditor(); - void setReadOnly( bool readOnly ); + explicit OptionSetEditor( QWidget *parent ); + ~OptionSetEditor(); + void setReadOnly( bool readOnly ); protected: - /** + /** * Returns the editor for the name of the OptionSet. * Derived classes are responsable of filling this UI element and reading back data from it. */ - KLineEdit * nameEdit() const; + KLineEdit * nameEdit() const; - /** + /** * Returns the editor for the description of the OptionSet. * Derived classes are responsable of filling this UI element and reading back data from it. */ - KTextEdit * descriptionEdit() const; + KTextEdit * descriptionEdit() const; protected slots: - /** + /** * Handles editing of the name field. * Pure virtual slot. Derived classes must provide an implementation. */ - virtual void slotNameEditTextEdited( const QString &newName ) = 0; + virtual void slotNameEditTextEdited( const QString &newName ) = 0; private: - KLineEdit * mNameEdit; ///< The editor for the OptionSet name - KTextEdit * mDescriptionEdit; ///< The editor for the OptionSet description + KLineEdit * mNameEdit; ///< The editor for the OptionSet name + KTextEdit * mDescriptionEdit; ///< The editor for the OptionSet description }; diff -Nru kdepim-4.12.97/messagelist/utils/themecombobox.cpp kdepim-4.13.0/messagelist/utils/themecombobox.cpp --- kdepim-4.12.97/messagelist/utils/themecombobox.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/themecombobox.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -31,98 +31,98 @@ using namespace MessageList::Utils; ThemeComboBox::ThemeComboBox( QWidget * parent ) -: KComboBox( parent ), d( new ThemeComboBoxPrivate( this ) ) + : KComboBox( parent ), d( new ThemeComboBoxPrivate( this ) ) { - if( Manager::instance() ) - d->slotLoadThemes(); - else - setEnabled(false); + if( Manager::instance() ) + d->slotLoadThemes(); + else + setEnabled(false); } ThemeComboBox::~ThemeComboBox() { - delete d; + delete d; } QString ThemeComboBox::currentTheme() const { - return itemData( currentIndex() ).toString(); + return itemData( currentIndex() ).toString(); } void ThemeComboBox::writeDefaultConfig() const { - KConfigGroup group( Settings::self()->config(), "MessageListView::StorageModelThemes" ); + KConfigGroup group( Settings::self()->config(), "MessageListView::StorageModelThemes" ); - const QString themeID = currentTheme(); - group.writeEntry( QLatin1String( "DefaultSet" ), themeID ); + const QString themeID = currentTheme(); + group.writeEntry( QLatin1String( "DefaultSet" ), themeID ); - Manager::instance()->themesConfigurationCompleted(); + Manager::instance()->themesConfigurationCompleted(); } void ThemeComboBox::writeStorageModelConfig( const Akonadi::Collection &col, bool isPrivateSetting ) const { - if ( col.isValid() ) - writeStorageModelConfig( QString::number( col.id() ), isPrivateSetting ); + if ( col.isValid() ) + writeStorageModelConfig( QString::number( col.id() ), isPrivateSetting ); } void ThemeComboBox::writeStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool isPrivateSetting ) const { - writeStorageModelConfig( storageModel->id(), isPrivateSetting ); + writeStorageModelConfig( storageModel->id(), isPrivateSetting ); } void ThemeComboBox::writeStorageModelConfig( const QString &id, bool isPrivateSetting )const { - QString themeID; - if ( isPrivateSetting ) { - themeID = currentTheme(); - } else { // explicitly use default theme id when using default theme. - themeID = Manager::instance()->defaultTheme()->id(); - } - Manager::instance()->saveThemeForStorageModel( id, themeID, isPrivateSetting ); - Manager::instance()->themesConfigurationCompleted(); + QString themeID; + if ( isPrivateSetting ) { + themeID = currentTheme(); + } else { // explicitly use default theme id when using default theme. + themeID = Manager::instance()->defaultTheme()->id(); + } + Manager::instance()->saveThemeForStorageModel( id, themeID, isPrivateSetting ); + Manager::instance()->themesConfigurationCompleted(); } void ThemeComboBox::readStorageModelConfig( const Akonadi::Collection& col, bool &isPrivateSetting ) { - const Theme *theme = Manager::instance()->themeForStorageModel( col, &isPrivateSetting ); - d->setCurrentTheme( theme ); + const Theme *theme = Manager::instance()->themeForStorageModel( col, &isPrivateSetting ); + d->setCurrentTheme( theme ); } void ThemeComboBox::readStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool &isPrivateSetting ) { - const Theme *theme = Manager::instance()->themeForStorageModel( storageModel, &isPrivateSetting ); - d->setCurrentTheme( theme ); + const Theme *theme = Manager::instance()->themeForStorageModel( storageModel, &isPrivateSetting ); + d->setCurrentTheme( theme ); } void ThemeComboBox::selectDefault() { - const Theme *defaultTheme = Manager::instance()->defaultTheme(); - d->setCurrentTheme( defaultTheme ); + const Theme *defaultTheme = Manager::instance()->defaultTheme(); + d->setCurrentTheme( defaultTheme ); } void ThemeComboBoxPrivate::slotLoadThemes() { - q->clear(); + q->clear(); - // Get all message list themes and sort them into alphabetical order. - QList< Theme * > themes = Manager::instance()->themes().values(); - qSort( themes.begin(), themes.end(), MessageList::Core::Theme::compareName ); - - foreach( const Theme * theme, themes ) - { - q->addItem( theme->name(), QVariant( theme->id() ) ); - } + // Get all message list themes and sort them into alphabetical order. + QList< Theme * > themes = Manager::instance()->themes().values(); + qSort( themes.begin(), themes.end(), MessageList::Core::Theme::compareName ); + + foreach( const Theme * theme, themes ) + { + q->addItem( theme->name(), QVariant( theme->id() ) ); + } } void ThemeComboBoxPrivate::setCurrentTheme( const Theme *theme ) { - Q_ASSERT( theme != 0 ); + Q_ASSERT( theme != 0 ); - const QString themeID = theme->id(); - const int themeIndex = q->findData( QVariant( themeID ) ); - q->setCurrentIndex( themeIndex ); + const QString themeID = theme->id(); + const int themeIndex = q->findData( QVariant( themeID ) ); + q->setCurrentIndex( themeIndex ); } #include "moc_themecombobox.cpp" diff -Nru kdepim-4.12.97/messagelist/utils/themecombobox.h kdepim-4.13.0/messagelist/utils/themecombobox.h --- kdepim-4.12.97/messagelist/utils/themecombobox.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/themecombobox.h 2014-04-10 07:40:20.000000000 +0000 @@ -43,30 +43,30 @@ */ class MESSAGELIST_EXPORT ThemeComboBox : public KComboBox { - Q_OBJECT + Q_OBJECT public: - explicit ThemeComboBox( QWidget * parent); - ~ThemeComboBox(); + explicit ThemeComboBox( QWidget * parent); + ~ThemeComboBox(); - QString currentTheme() const; + QString currentTheme() const; - void writeDefaultConfig() const; + void writeDefaultConfig() const; - void writeStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool isPrivateSetting ) const; - void writeStorageModelConfig( const Akonadi::Collection &col, bool isPrivateSetting ) const; - void writeStorageModelConfig( const QString &id, bool isPrivateSetting )const; + void writeStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool isPrivateSetting ) const; + void writeStorageModelConfig( const Akonadi::Collection &col, bool isPrivateSetting ) const; + void writeStorageModelConfig( const QString &id, bool isPrivateSetting )const; - void readStorageModelConfig( const Akonadi::Collection& col, bool &isPrivateSetting ); - void readStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool &isPrivateSetting ); + void readStorageModelConfig( const Akonadi::Collection& col, bool &isPrivateSetting ); + void readStorageModelConfig( MessageList::Core::StorageModel *storageModel, bool &isPrivateSetting ); public Q_SLOTS: - void selectDefault(); + void selectDefault(); private: - Q_PRIVATE_SLOT(d, void slotLoadThemes()) - ThemeComboBoxPrivate * const d; + Q_PRIVATE_SLOT(d, void slotLoadThemes()) + ThemeComboBoxPrivate * const d; }; } // namespace Utils diff -Nru kdepim-4.12.97/messagelist/utils/themeconfigbutton.cpp kdepim-4.13.0/messagelist/utils/themeconfigbutton.cpp --- kdepim-4.12.97/messagelist/utils/themeconfigbutton.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/themeconfigbutton.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -32,48 +32,48 @@ class MessageList::Utils::ThemeConfigButtonPrivate { public: - ThemeConfigButtonPrivate( ThemeConfigButton *owner ) - : q( owner ), mThemeComboBox( 0 ) { } + ThemeConfigButtonPrivate( ThemeConfigButton *owner ) + : q( owner ), mThemeComboBox( 0 ) { } - ThemeConfigButton * const q; + ThemeConfigButton * const q; - const ThemeComboBox * mThemeComboBox; + const ThemeComboBox * mThemeComboBox; - void slotConfigureThemes(); + void slotConfigureThemes(); }; void ThemeConfigButtonPrivate::slotConfigureThemes() { - QString currentThemeID; - if ( mThemeComboBox != 0 ) - currentThemeID = mThemeComboBox->currentTheme(); + QString currentThemeID; + if ( mThemeComboBox != 0 ) + currentThemeID = mThemeComboBox->currentTheme(); - ConfigureThemesDialog *dialog = new ConfigureThemesDialog( q->window() ); - dialog->selectTheme( currentThemeID ); + ConfigureThemesDialog *dialog = new ConfigureThemesDialog( q->window() ); + dialog->selectTheme( currentThemeID ); - QObject::connect( dialog, SIGNAL(okClicked()), - q, SIGNAL(configureDialogCompleted()) ); + QObject::connect( dialog, SIGNAL(okClicked()), + q, SIGNAL(configureDialogCompleted()) ); - dialog->show(); + dialog->show(); } ThemeConfigButton::ThemeConfigButton( QWidget * parent, const ThemeComboBox * themeComboBox ) -: KPushButton( i18n( "Configure..." ), parent ), d( new ThemeConfigButtonPrivate( this ) ) + : KPushButton( i18n( "Configure..." ), parent ), d( new ThemeConfigButtonPrivate( this ) ) { - d->mThemeComboBox = themeComboBox; - connect( this, SIGNAL(pressed()), - this, SLOT(slotConfigureThemes()) ); - - //Keep theme combo up-to-date with any changes made in the configure dialog. - if ( d->mThemeComboBox != 0 ) - connect( this, SIGNAL(configureDialogCompleted()), - d->mThemeComboBox, SLOT(slotLoadThemes()) ); + d->mThemeComboBox = themeComboBox; + connect( this, SIGNAL(pressed()), + this, SLOT(slotConfigureThemes()) ); + + //Keep theme combo up-to-date with any changes made in the configure dialog. + if ( d->mThemeComboBox != 0 ) + connect( this, SIGNAL(configureDialogCompleted()), + d->mThemeComboBox, SLOT(slotLoadThemes()) ); } ThemeConfigButton::~ThemeConfigButton() { - delete d; + delete d; } diff -Nru kdepim-4.12.97/messagelist/utils/themeconfigbutton.h kdepim-4.13.0/messagelist/utils/themeconfigbutton.h --- kdepim-4.12.97/messagelist/utils/themeconfigbutton.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/themeconfigbutton.h 2014-04-10 07:40:20.000000000 +0000 @@ -37,27 +37,27 @@ */ class MESSAGELIST_EXPORT ThemeConfigButton : public KPushButton { - Q_OBJECT + Q_OBJECT public: - /** Constructor. + /** Constructor. * @param parent The parent widget for the button. * @param themeComboBox Optional ThemeComboBox to be kept in sync * with changes made by the configure dialog. */ - explicit ThemeConfigButton( QWidget * parent, const ThemeComboBox * themeComboBox = 0 ); - ~ThemeConfigButton(); + explicit ThemeConfigButton( QWidget * parent, const ThemeComboBox * themeComboBox = 0 ); + ~ThemeConfigButton(); signals: - /** + /** * A signal emitted when configure dialog has been successfully completed. */ - void configureDialogCompleted(); + void configureDialogCompleted(); private: - Q_PRIVATE_SLOT(d, void slotConfigureThemes()) + Q_PRIVATE_SLOT(d, void slotConfigureThemes()) - ThemeConfigButtonPrivate * const d; + ThemeConfigButtonPrivate * const d; }; } // namespace Utils diff -Nru kdepim-4.12.97/messagelist/utils/themeeditor.cpp kdepim-4.13.0/messagelist/utils/themeeditor.cpp --- kdepim-4.12.97/messagelist/utils/themeeditor.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/themeeditor.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -67,78 +67,78 @@ ThemeColumnPropertiesDialog::ThemeColumnPropertiesDialog( QWidget * parent, Theme::Column * column, const QString &title ) - : KDialog( parent ), mColumn( column ) + : KDialog( parent ), mColumn( column ) { - //setAttribute( Qt::WA_DeleteOnClose ); - setWindowModality( Qt::ApplicationModal ); // FIXME: Sure ? - setButtons( Ok | Cancel ); - setWindowTitle( title ); + //setAttribute( Qt::WA_DeleteOnClose ); + setWindowModality( Qt::ApplicationModal ); // FIXME: Sure ? + setButtons( Ok | Cancel ); + setWindowTitle( title ); - QWidget * base = new QWidget( this ); - setMainWidget( base ); + QWidget * base = new QWidget( this ); + setMainWidget( base ); - QGridLayout * g = new QGridLayout( base ); + QGridLayout * g = new QGridLayout( base ); - QLabel * l; + QLabel * l; - l = new QLabel( i18nc( "@label:textbox Property name", "Name:" ), base ); - g->addWidget( l, 0, 0 ); + l = new QLabel( i18nc( "@label:textbox Property name", "Name:" ), base ); + g->addWidget( l, 0, 0 ); - mNameEdit = new KLineEdit( base ); - mNameEdit->setToolTip( i18n( "The label that will be displayed in the column header." ) ); - g->addWidget( mNameEdit, 0, 1 ); + mNameEdit = new KLineEdit( base ); + mNameEdit->setToolTip( i18n( "The label that will be displayed in the column header." ) ); + g->addWidget( mNameEdit, 0, 1 ); - l = new QLabel( i18n( "Header click sorts messages:" ), base ); - g->addWidget( l, 1, 0 ); + l = new QLabel( i18n( "Header click sorts messages:" ), base ); + g->addWidget( l, 1, 0 ); - mMessageSortingCombo = new KComboBox( base ); - mMessageSortingCombo->setToolTip( i18n( "The sorting order that clicking on this column header will switch to." ) ); - g->addWidget( mMessageSortingCombo, 1, 1 ); + mMessageSortingCombo = new KComboBox( base ); + mMessageSortingCombo->setToolTip( i18n( "The sorting order that clicking on this column header will switch to." ) ); + g->addWidget( mMessageSortingCombo, 1, 1 ); - mVisibleByDefaultCheck = new QCheckBox( i18n( "Visible by default" ), base ); - mVisibleByDefaultCheck->setToolTip( i18n( "Check this if this column should be visible when the theme is selected." ) ); - g->addWidget( mVisibleByDefaultCheck, 2, 1 ); + mVisibleByDefaultCheck = new QCheckBox( i18n( "Visible by default" ), base ); + mVisibleByDefaultCheck->setToolTip( i18n( "Check this if this column should be visible when the theme is selected." ) ); + g->addWidget( mVisibleByDefaultCheck, 2, 1 ); - mIsSenderOrReceiverCheck = new QCheckBox( i18n( "Contains \"Sender or Receiver\" field" ), base ); - mIsSenderOrReceiverCheck->setToolTip( i18n( "Check this if this column label should be updated depending on the folder \"inbound\"/\"outbound\" type." ) ); - g->addWidget( mIsSenderOrReceiverCheck, 3, 1 ); + mIsSenderOrReceiverCheck = new QCheckBox( i18n( "Contains \"Sender or Receiver\" field" ), base ); + mIsSenderOrReceiverCheck->setToolTip( i18n( "Check this if this column label should be updated depending on the folder \"inbound\"/\"outbound\" type." ) ); + g->addWidget( mIsSenderOrReceiverCheck, 3, 1 ); - g->setColumnStretch( 1, 1 ); - g->setRowStretch( 10, 1 ); + g->setColumnStretch( 1, 1 ); + g->setRowStretch( 10, 1 ); - connect( this, SIGNAL(okClicked()), - SLOT(slotOkButtonClicked()) ); + connect( this, SIGNAL(okClicked()), + SLOT(slotOkButtonClicked()) ); - // Display the current settings - mNameEdit->setText( mColumn->label() ); - mVisibleByDefaultCheck->setChecked( mColumn->visibleByDefault() ); - mIsSenderOrReceiverCheck->setChecked( mColumn->isSenderOrReceiver() ); - ComboBoxUtils::fillIntegerOptionCombo( mMessageSortingCombo, SortOrder::enumerateMessageSortingOptions( Aggregation::PerfectReferencesAndSubject ) ); - ComboBoxUtils::setIntegerOptionComboValue( mMessageSortingCombo, mColumn->messageSorting() ); + // Display the current settings + mNameEdit->setText( mColumn->label() ); + mVisibleByDefaultCheck->setChecked( mColumn->visibleByDefault() ); + mIsSenderOrReceiverCheck->setChecked( mColumn->isSenderOrReceiver() ); + ComboBoxUtils::fillIntegerOptionCombo( mMessageSortingCombo, SortOrder::enumerateMessageSortingOptions( Aggregation::PerfectReferencesAndSubject ) ); + ComboBoxUtils::setIntegerOptionComboValue( mMessageSortingCombo, mColumn->messageSorting() ); } void ThemeColumnPropertiesDialog::slotOkButtonClicked() { - QString text = mNameEdit->text(); - if ( text.isEmpty() ) - text = i18n( "Unnamed Column" ); - mColumn->setLabel( text ); - mColumn->setVisibleByDefault( mVisibleByDefaultCheck->isChecked() ); - mColumn->setIsSenderOrReceiver( mIsSenderOrReceiverCheck->isChecked() ); - mColumn->setMessageSorting( - static_cast< SortOrder::MessageSorting >( - ComboBoxUtils::getIntegerOptionComboValue( mMessageSortingCombo, SortOrder::NoMessageSorting ) - ) - ); + QString text = mNameEdit->text(); + if ( text.isEmpty() ) + text = i18n( "Unnamed Column" ); + mColumn->setLabel( text ); + mColumn->setVisibleByDefault( mVisibleByDefaultCheck->isChecked() ); + mColumn->setIsSenderOrReceiver( mIsSenderOrReceiverCheck->isChecked() ); + mColumn->setMessageSorting( + static_cast< SortOrder::MessageSorting >( + ComboBoxUtils::getIntegerOptionComboValue( mMessageSortingCombo, SortOrder::NoMessageSorting ) + ) + ); - accept(); + accept(); } ThemeContentItemSourceLabel::ThemeContentItemSourceLabel( QWidget * parent, Theme::ContentItem::Type type ) - : QLabel( parent ), mType( type ) + : QLabel( parent ), mType( type ) { - setFrameStyle( QFrame::StyledPanel | QFrame::Raised ); + setFrameStyle( QFrame::StyledPanel | QFrame::Raised ); } ThemeContentItemSourceLabel::~ThemeContentItemSourceLabel() @@ -153,97 +153,97 @@ void ThemeContentItemSourceLabel::mousePressEvent( QMouseEvent * e ) { - if ( e->button() == Qt::LeftButton ) - mMousePressPoint = e->pos(); + if ( e->button() == Qt::LeftButton ) + mMousePressPoint = e->pos(); } void ThemeContentItemSourceLabel::mouseMoveEvent( QMouseEvent * e ) { - if ( e->buttons() & Qt::LeftButton ) - { - const QPoint diff = mMousePressPoint - e->pos(); - if ( diff.manhattanLength() > 4 ) - startDrag(); - } + if ( e->buttons() & Qt::LeftButton ) + { + const QPoint diff = mMousePressPoint - e->pos(); + if ( diff.manhattanLength() > 4 ) + startDrag(); + } } void ThemeContentItemSourceLabel::startDrag() { - //QPixmap pix = QPixmap::grabWidget( this ); - //QPixmap alpha( pix.width(), pix.height() ); - //alpha.fill(0x0f0f0f0f); - //pix.setAlphaChannel( alpha ); // <-- this crashes... no alpha for dragged pixmap :( - QMimeData * data = new QMimeData(); - QByteArray arry; - arry.resize( sizeof( Theme::ContentItem::Type ) ); - *( ( Theme::ContentItem::Type * ) arry.data() ) = mType; - data->setData( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ), arry ); - QDrag * drag = new QDrag( this ); - drag->setMimeData( data ); - //drag->setPixmap( pix ); - //drag->setHotSpot( mapFromGlobal( QCursor::pos() ) ); - drag->exec( Qt::CopyAction, Qt::CopyAction ); + //QPixmap pix = QPixmap::grabWidget( this ); + //QPixmap alpha( pix.width(), pix.height() ); + //alpha.fill(0x0f0f0f0f); + //pix.setAlphaChannel( alpha ); // <-- this crashes... no alpha for dragged pixmap :( + QMimeData * data = new QMimeData(); + QByteArray arry; + arry.resize( sizeof( Theme::ContentItem::Type ) ); + *( ( Theme::ContentItem::Type * ) arry.data() ) = mType; + data->setData( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ), arry ); + QDrag * drag = new QDrag( this ); + drag->setMimeData( data ); + //drag->setPixmap( pix ); + //drag->setHotSpot( mapFromGlobal( QCursor::pos() ) ); + drag->exec( Qt::CopyAction, Qt::CopyAction ); } ThemePreviewDelegate::ThemePreviewDelegate( QAbstractItemView * parent ) - : ThemeDelegate( parent ) + : ThemeDelegate( parent ) { - mRowMapper = new ModelInvariantRowMapper(); + mRowMapper = new ModelInvariantRowMapper(); - mSampleGroupHeaderItem = new GroupHeaderItem( i18n( "Message Group" ) ); + mSampleGroupHeaderItem = new GroupHeaderItem( i18n( "Message Group" ) ); - mSampleGroupHeaderItem->setDate( time( 0 ) ); - mSampleGroupHeaderItem->setMaxDate( time( 0 ) + 31337 ); - mSampleGroupHeaderItem->setSubject( i18n( "Very long subject very long subject very long subject very long subject very long subject very long" ) ); + mSampleGroupHeaderItem->setDate( time( 0 ) ); + mSampleGroupHeaderItem->setMaxDate( time( 0 ) + 31337 ); + mSampleGroupHeaderItem->setSubject( i18n( "Very long subject very long subject very long subject very long subject very long subject very long" ) ); - mSampleMessageItem = new FakeItem(); + mSampleMessageItem = new FakeItem(); - mSampleMessageItem->setDate( time( 0 ) ); - mSampleMessageItem->setSize( 0x31337 ); - mSampleMessageItem->setMaxDate( time( 0 ) + 31337 ); - mSampleMessageItem->setSender( i18n( "Sender" ) ); - mSampleMessageItem->setReceiver( i18n( "Receiver" ) ); - mSampleMessageItem->setSubject( i18n( "Very long subject very long subject very long subject very long subject very long subject very long" ) ); - mSampleMessageItem->setSignatureState( MessageItem::FullySigned ); - mSampleMessageItem->setEncryptionState( MessageItem::FullyEncrypted ); + mSampleMessageItem->setDate( time( 0 ) ); + mSampleMessageItem->setSize( 0x31337 ); + mSampleMessageItem->setMaxDate( time( 0 ) + 31337 ); + mSampleMessageItem->setSender( i18n( "Sender" ) ); + mSampleMessageItem->setReceiver( i18n( "Receiver" ) ); + mSampleMessageItem->setSubject( i18n( "Very long subject very long subject very long subject very long subject very long subject very long" ) ); + mSampleMessageItem->setSignatureState( MessageItem::FullySigned ); + mSampleMessageItem->setEncryptionState( MessageItem::FullyEncrypted ); - QList< MessageItem::Tag * > list; - list.append( new MessageItem::Tag( SmallIcon( QLatin1String( "feed-subscribe" ) ), i18n( "Sample Tag 1" ), QString() ) ); - list.append( new MessageItem::Tag( SmallIcon( QLatin1String( "feed-subscribe" ) ), i18n( "Sample Tag 2" ), QString() ) ); - list.append( new MessageItem::Tag( SmallIcon( QLatin1String( "feed-subscribe" ) ), i18n( "Sample Tag 3" ), QString() ) ); - mSampleMessageItem->setFakeTags( list ); + QList< MessageItem::Tag * > list; + list.append( new MessageItem::Tag( SmallIcon( QLatin1String( "feed-subscribe" ) ), i18n( "Sample Tag 1" ), QString() ) ); + list.append( new MessageItem::Tag( SmallIcon( QLatin1String( "feed-subscribe" ) ), i18n( "Sample Tag 2" ), QString() ) ); + list.append( new MessageItem::Tag( SmallIcon( QLatin1String( "feed-subscribe" ) ), i18n( "Sample Tag 3" ), QString() ) ); + mSampleMessageItem->setFakeTags( list ); - mRowMapper->createModelInvariantIndex( 0, mSampleMessageItem ); + mRowMapper->createModelInvariantIndex( 0, mSampleMessageItem ); - mSampleGroupHeaderItem->rawAppendChildItem( mSampleMessageItem ); - mSampleMessageItem->setParent( mSampleGroupHeaderItem ); + mSampleGroupHeaderItem->rawAppendChildItem( mSampleMessageItem ); + mSampleMessageItem->setParent( mSampleGroupHeaderItem ); - Akonadi::MessageStatus stat; + Akonadi::MessageStatus stat; - stat.fromQInt32( 0x7fffffff ); - stat.setQueued( false ); - stat.setSent( false ); - stat.setSpam( true ); - stat.setWatched( true ); - stat.setHasInvitation(); - //stat.setHasAttachment( false ); + stat.fromQInt32( 0x7fffffff ); + stat.setQueued( false ); + stat.setSent( false ); + stat.setSpam( true ); + stat.setWatched( true ); + stat.setHasInvitation(); + //stat.setHasAttachment( false ); - mSampleMessageItem->setStatus( stat ); + mSampleMessageItem->setStatus( stat ); } ThemePreviewDelegate::~ThemePreviewDelegate() { - delete mSampleGroupHeaderItem; - //delete mSampleMessageItem; (deleted by the parent) - delete mRowMapper; + delete mSampleGroupHeaderItem; + //delete mSampleMessageItem; (deleted by the parent) + delete mRowMapper; } Item * ThemePreviewDelegate::itemFromIndex( const QModelIndex &index ) const { - if ( index.parent().isValid() ) - return mSampleMessageItem; + if ( index.parent().isValid() ) + return mSampleMessageItem; - return mSampleGroupHeaderItem; + return mSampleGroupHeaderItem; } @@ -251,32 +251,32 @@ ThemePreviewWidget::ThemePreviewWidget( QWidget * parent ) - : QTreeWidget( parent ), - mTheme( 0 ) + : QTreeWidget( parent ), + mTheme( 0 ) { - mSelectedThemeContentItem = 0; - mSelectedThemeColumn = 0; - mFirstShow = true; - mReadOnly = false; - - mDelegate = new ThemePreviewDelegate( this ); - setItemDelegate( mDelegate ); - setRootIsDecorated( false ); - viewport()->setAcceptDrops( true ); - - header()->setContextMenuPolicy( Qt::CustomContextMenu ); // make sure it's true - connect( header(), SIGNAL(customContextMenuRequested(QPoint)), - SLOT(slotHeaderContextMenuRequested(QPoint)) ); - - mGroupHeaderSampleItem = new QTreeWidgetItem( this ); - mGroupHeaderSampleItem->setText( 0, QString() ); - mGroupHeaderSampleItem->setFlags( Qt::ItemIsEnabled ); + mSelectedThemeContentItem = 0; + mSelectedThemeColumn = 0; + mFirstShow = true; + mReadOnly = false; - QTreeWidgetItem * m = new QTreeWidgetItem( mGroupHeaderSampleItem ); - m->setText( 0, QString() ); + mDelegate = new ThemePreviewDelegate( this ); + setItemDelegate( mDelegate ); + setRootIsDecorated( false ); + viewport()->setAcceptDrops( true ); + + header()->setContextMenuPolicy( Qt::CustomContextMenu ); // make sure it's true + connect( header(), SIGNAL(customContextMenuRequested(QPoint)), + SLOT(slotHeaderContextMenuRequested(QPoint)) ); + + mGroupHeaderSampleItem = new QTreeWidgetItem( this ); + mGroupHeaderSampleItem->setText( 0, QString() ); + mGroupHeaderSampleItem->setFlags( Qt::ItemIsEnabled ); - mGroupHeaderSampleItem->setExpanded( true ); - header()->setMovable(false); + QTreeWidgetItem * m = new QTreeWidgetItem( mGroupHeaderSampleItem ); + m->setText( 0, QString() ); + + mGroupHeaderSampleItem->setExpanded( true ); + header()->setMovable(false); } ThemePreviewWidget::~ThemePreviewWidget() @@ -285,1065 +285,1065 @@ QSize ThemePreviewWidget::sizeHint() const { - return QSize( 350, 180 ); + return QSize( 350, 180 ); } void ThemePreviewWidget::setReadOnly( bool readOnly ) { - mReadOnly = readOnly; + mReadOnly = readOnly; } void ThemePreviewWidget::applyThemeColumnWidths() { - if ( !mTheme ) - return; + if ( !mTheme ) + return; - const QList< Theme::Column * > & columns = mTheme->columns(); + const QList< Theme::Column * > & columns = mTheme->columns(); - if ( columns.isEmpty() ) - { - viewport()->update(); // trigger a repaint - return; - } + if ( columns.isEmpty() ) + { + viewport()->update(); // trigger a repaint + return; + } - // Now we want to distribute the available width on all the columns. - // The algorithm used here is very similar to the one used in View::applyThemeColumns(). - // It just takes care of ALL the columns instead of the visible ones. - - QList< Theme::Column * >::ConstIterator it; - - // Gather size hints for all sections. - int idx = 0; - int totalVisibleWidthHint = 0; - QList< Theme::Column * >::ConstIterator end( columns.constEnd() ); - - for ( it = columns.constBegin(); it != end; ++it ) - { - totalVisibleWidthHint += mDelegate->sizeHintForItemTypeAndColumn( Item::Message, idx ).width(); - idx++; - } - - if ( totalVisibleWidthHint < 16 ) - totalVisibleWidthHint = 16; // be reasonable - - // Now we can compute proportional widths. - - idx = 0; - - QList< int > realWidths; - int totalVisibleWidth = 0; - - end = columns.constEnd(); - for ( it = columns.constBegin(); it != end; ++it ) - { - int hintWidth = mDelegate->sizeHintForItemTypeAndColumn( Item::Message, idx ).width(); - int realWidth; - if ( ( *it )->containsTextItems() ) - { - // the column contains text items, it should get more space - realWidth = ( ( hintWidth * viewport()->width() ) / totalVisibleWidthHint ) - 2; // -2 is heuristic - if ( realWidth < ( hintWidth + 2 ) ) - realWidth = hintWidth + 2; // can't be less - } else { - // the column contains no text items, it should get just a little bit more than its sizeHint(). - realWidth = hintWidth + 2; + // Now we want to distribute the available width on all the columns. + // The algorithm used here is very similar to the one used in View::applyThemeColumns(). + // It just takes care of ALL the columns instead of the visible ones. + + QList< Theme::Column * >::ConstIterator it; + + // Gather size hints for all sections. + int idx = 0; + int totalVisibleWidthHint = 0; + QList< Theme::Column * >::ConstIterator end( columns.constEnd() ); + + for ( it = columns.constBegin(); it != end; ++it ) + { + totalVisibleWidthHint += mDelegate->sizeHintForItemTypeAndColumn( Item::Message, idx ).width(); + idx++; } - realWidths.append( realWidth ); - totalVisibleWidth += realWidth; + if ( totalVisibleWidthHint < 16 ) + totalVisibleWidthHint = 16; // be reasonable + + // Now we can compute proportional widths. - idx++; - } + idx = 0; - idx = 0; + QList< int > realWidths; + int totalVisibleWidth = 0; + + end = columns.constEnd(); + for ( it = columns.constBegin(); it != end; ++it ) + { + int hintWidth = mDelegate->sizeHintForItemTypeAndColumn( Item::Message, idx ).width(); + int realWidth; + if ( ( *it )->containsTextItems() ) + { + // the column contains text items, it should get more space + realWidth = ( ( hintWidth * viewport()->width() ) / totalVisibleWidthHint ) - 2; // -2 is heuristic + if ( realWidth < ( hintWidth + 2 ) ) + realWidth = hintWidth + 2; // can't be less + } else { + // the column contains no text items, it should get just a little bit more than its sizeHint(). + realWidth = hintWidth + 2; + } + + realWidths.append( realWidth ); + totalVisibleWidth += realWidth; + + idx++; + } + + idx = 0; + + totalVisibleWidth += 4; // account for some view's border + + if ( totalVisibleWidth < viewport()->width() ) + { + // give the additional space to the text columns + // also give more space to the first ones and less space to the last ones + int available = viewport()->width() - totalVisibleWidth; + + for ( it = columns.begin(); it != columns.end(); ++it ) + { + if ( ( ( *it )->visibleByDefault() || ( idx == 0 ) ) && ( *it )->containsTextItems() ) + { + // give more space to this column + available >>= 1; // eat half of the available space + realWidths[ idx ] += available; // and give it to this column + } + + idx++; + } + + // if any space is still available, give it to the first column + if ( available ) + realWidths[ 0 ] += available; + } - totalVisibleWidth += 4; // account for some view's border - if ( totalVisibleWidth < viewport()->width() ) - { - // give the additional space to the text columns - // also give more space to the first ones and less space to the last ones - int available = viewport()->width() - totalVisibleWidth; + idx = 0; + // We're ready. + // Assign widths. Hide the sections that are not visible by default, show the other ones. for ( it = columns.begin(); it != columns.end(); ++it ) { - if ( ( ( *it )->visibleByDefault() || ( idx == 0 ) ) && ( *it )->containsTextItems() ) - { - // give more space to this column - available >>= 1; // eat half of the available space - realWidths[ idx ] += available; // and give it to this column - } - - idx++; - } - - // if any space is still available, give it to the first column - if ( available ) - realWidths[ 0 ] += available; - } - - - idx = 0; - - // We're ready. - // Assign widths. Hide the sections that are not visible by default, show the other ones. - for ( it = columns.begin(); it != columns.end(); ++it ) - { - header()->resizeSection( idx, realWidths[ idx ] ); - idx++; - } + header()->resizeSection( idx, realWidths[ idx ] ); + idx++; + } #if 0 - if( mTheme->viewHeaderPolicy() == Theme::NeverShowHeader ) - header()->hide(); - else - header()->show(); + if( mTheme->viewHeaderPolicy() == Theme::NeverShowHeader ) + header()->hide(); + else + header()->show(); #endif } void ThemePreviewWidget::setTheme( Theme * theme ) { - bool themeChanged = theme != mTheme; + bool themeChanged = theme != mTheme; + + mSelectedThemeContentItem = 0; + mThemeSelectedContentItemRect = QRect(); + mDropIndicatorPoint1 = QPoint(); + mDropIndicatorPoint2 = QPoint(); + mTheme = theme; + mDelegate->setTheme( theme ); + if (!mTheme) + return; + mGroupHeaderSampleItem->setExpanded( true ); - mSelectedThemeContentItem = 0; - mThemeSelectedContentItemRect = QRect(); - mDropIndicatorPoint1 = QPoint(); - mDropIndicatorPoint2 = QPoint(); - mTheme = theme; - mDelegate->setTheme( theme ); - if (!mTheme) - return; - mGroupHeaderSampleItem->setExpanded( true ); - - const QList< Theme::Column * > & columns = mTheme->columns(); - - setColumnCount( columns.count() ); - - QStringList headerLabels; - QList< Theme::Column * >::ConstIterator end( columns.constEnd() ); - for( QList< Theme::Column * >::ConstIterator it = columns.constBegin(); it != end; ++it ) - { - QString label = ( *it )->label(); - if ( ( *it )->visibleByDefault() ) - label += QString::fromLatin1( " (%1)" ).arg( i18nc( "Indicates whether or not a header label is visible", "Visible") ); - - headerLabels.append( label ); - } + const QList< Theme::Column * > & columns = mTheme->columns(); - setHeaderLabels( headerLabels ); + setColumnCount( columns.count() ); - if ( themeChanged ) - applyThemeColumnWidths(); + QStringList headerLabels; + QList< Theme::Column * >::ConstIterator end( columns.constEnd() ); + for( QList< Theme::Column * >::ConstIterator it = columns.constBegin(); it != end; ++it ) + { + QString label = ( *it )->label(); + if ( ( *it )->visibleByDefault() ) + label += QString::fromLatin1( " (%1)" ).arg( i18nc( "Indicates whether or not a header label is visible", "Visible") ); - viewport()->update(); // trigger a repaint + headerLabels.append( label ); + } + + setHeaderLabels( headerLabels ); + + if ( themeChanged ) + applyThemeColumnWidths(); + + viewport()->update(); // trigger a repaint } void ThemePreviewWidget::internalHandleDragEnterEvent( QDragEnterEvent * e ) { - e->ignore(); + e->ignore(); - if ( !e->mimeData() ) - return; - if ( !e->mimeData()->hasFormat( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ) ) ) - return; + if ( !e->mimeData() ) + return; + if ( !e->mimeData()->hasFormat( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ) ) ) + return; - e->accept(); + e->accept(); } void ThemePreviewWidget::showEvent( QShowEvent * e ) { - QTreeWidget::showEvent( e ); + QTreeWidget::showEvent( e ); - if ( mFirstShow ) - { - // Make sure we re-apply column widths the first time we're shown. - // The first "apply" call was made while the widget was still hidden and - // almost surely had wrong sizes. - applyThemeColumnWidths(); - mFirstShow = false; - } + if ( mFirstShow ) + { + // Make sure we re-apply column widths the first time we're shown. + // The first "apply" call was made while the widget was still hidden and + // almost surely had wrong sizes. + applyThemeColumnWidths(); + mFirstShow = false; + } } void ThemePreviewWidget::dragEnterEvent( QDragEnterEvent * e ) { - internalHandleDragEnterEvent( e ); + internalHandleDragEnterEvent( e ); - mThemeSelectedContentItemRect = QRect(); + mThemeSelectedContentItemRect = QRect(); - viewport()->update(); // trigger a repaint + viewport()->update(); // trigger a repaint } void ThemePreviewWidget::internalHandleDragMoveEvent( QDragMoveEvent * e ) { - e->ignore(); + e->ignore(); - if ( mReadOnly ) - return; + if ( mReadOnly ) + return; - if ( !e->mimeData() ) - return; - if ( !e->mimeData()->hasFormat( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ) ) ) - return; + if ( !e->mimeData() ) + return; + if ( !e->mimeData()->hasFormat( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ) ) ) + return; - QByteArray arry = e->mimeData()->data(QLatin1String( gThemeContentItemTypeDndMimeDataFormat ) ); + QByteArray arry = e->mimeData()->data(QLatin1String( gThemeContentItemTypeDndMimeDataFormat ) ); - if ( arry.size() != sizeof( Theme::ContentItem::Type ) ) - return; // ugh + if ( arry.size() != sizeof( Theme::ContentItem::Type ) ) + return; // ugh - Theme::ContentItem::Type type = *( ( Theme::ContentItem::Type * ) arry.data() ); + Theme::ContentItem::Type type = *( ( Theme::ContentItem::Type * ) arry.data() ); - if ( !computeContentItemInsertPosition( e->pos(), type ) ) - return; + if ( !computeContentItemInsertPosition( e->pos(), type ) ) + return; - e->accept(); + e->accept(); } void ThemePreviewWidget::dragMoveEvent( QDragMoveEvent * e ) { - if ( mReadOnly ) - return; + if ( mReadOnly ) + return; - internalHandleDragMoveEvent( e ); + internalHandleDragMoveEvent( e ); - mThemeSelectedContentItemRect = QRect(); + mThemeSelectedContentItemRect = QRect(); - viewport()->update(); // trigger a repaint + viewport()->update(); // trigger a repaint } void ThemePreviewWidget::dropEvent( QDropEvent * e ) { - mDropIndicatorPoint1 = mDropIndicatorPoint2; + mDropIndicatorPoint1 = mDropIndicatorPoint2; - e->ignore(); + e->ignore(); - if ( mReadOnly ) - return; + if ( mReadOnly ) + return; - if ( !e->mimeData() ) - return; + if ( !e->mimeData() ) + return; - if ( !e->mimeData()->hasFormat( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ) ) ) - return; + if ( !e->mimeData()->hasFormat( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ) ) ) + return; - QByteArray arry = e->mimeData()->data( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ) ); + QByteArray arry = e->mimeData()->data( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ) ); - if ( arry.size() != sizeof( Theme::ContentItem::Type ) ) - return; // ugh + if ( arry.size() != sizeof( Theme::ContentItem::Type ) ) + return; // ugh - Theme::ContentItem::Type type = *( ( Theme::ContentItem::Type * ) arry.data() ); + Theme::ContentItem::Type type = *( ( Theme::ContentItem::Type * ) arry.data() ); - if ( !computeContentItemInsertPosition( e->pos(), type ) ) - { - viewport()->update(); - return; - } + if ( !computeContentItemInsertPosition( e->pos(), type ) ) + { + viewport()->update(); + return; + } - Theme::Row * row = 0; + Theme::Row * row = 0; - switch ( mRowInsertPosition ) - { + switch ( mRowInsertPosition ) + { case AboveRow: - row = new Theme::Row(); - if ( mDelegate->hitItem()->type() == Item::Message ) - const_cast< Theme::Column * >( mDelegate->hitColumn() )->insertMessageRow( mDelegate->hitRowIndex(), row ); - else - const_cast< Theme::Column * >( mDelegate->hitColumn() )->insertGroupHeaderRow( mDelegate->hitRowIndex(), row ); - break; + row = new Theme::Row(); + if ( mDelegate->hitItem()->type() == Item::Message ) + const_cast< Theme::Column * >( mDelegate->hitColumn() )->insertMessageRow( mDelegate->hitRowIndex(), row ); + else + const_cast< Theme::Column * >( mDelegate->hitColumn() )->insertGroupHeaderRow( mDelegate->hitRowIndex(), row ); + break; case InsideRow: - row = const_cast< Theme::Row * >( mDelegate->hitRow() ); - break; + row = const_cast< Theme::Row * >( mDelegate->hitRow() ); + break; case BelowRow: - row = new Theme::Row(); - if ( mDelegate->hitItem()->type() == Item::Message ) - const_cast< Theme::Column * >( mDelegate->hitColumn() )->insertMessageRow( mDelegate->hitRowIndex()+1, row ); - else - const_cast< Theme::Column * >( mDelegate->hitColumn() )->insertGroupHeaderRow( mDelegate->hitRowIndex()+1, row ); - break; - } - - if ( !row ) - return; - - Theme::ContentItem * ci = new Theme::ContentItem( type ); - if ( ci->canBeDisabled() ) - { - if ( ci->isClickable() ) - ci->setSoftenByBlendingWhenDisabled( true ); // default to softened - else - ci->setHideWhenDisabled( true ); // default to hidden - } + row = new Theme::Row(); + if ( mDelegate->hitItem()->type() == Item::Message ) + const_cast< Theme::Column * >( mDelegate->hitColumn() )->insertMessageRow( mDelegate->hitRowIndex()+1, row ); + else + const_cast< Theme::Column * >( mDelegate->hitColumn() )->insertGroupHeaderRow( mDelegate->hitRowIndex()+1, row ); + break; + } + + if ( !row ) + return; - int idx; + Theme::ContentItem * ci = new Theme::ContentItem( type ); + if ( ci->canBeDisabled() ) + { + if ( ci->isClickable() ) + ci->setSoftenByBlendingWhenDisabled( true ); // default to softened + else + ci->setHideWhenDisabled( true ); // default to hidden + } - switch( mItemInsertPosition ) - { + int idx; + + switch( mItemInsertPosition ) + { case OnLeftOfItem: - if ( !mDelegate->hitContentItem() ) - { - // bleah - delete ci; - return; - } - idx = mDelegate->hitContentItemRight() ? \ - row->rightItems().indexOf( const_cast< Theme::ContentItem * >( mDelegate->hitContentItem() ) ) : \ - row->leftItems().indexOf( const_cast< Theme::ContentItem * >( mDelegate->hitContentItem() ) ); - if ( idx < 0 ) - { - // bleah - delete ci; - return; - } - if ( mDelegate->hitContentItemRight() ) - row->insertRightItem( idx+1, ci ); - else - row->insertLeftItem( idx, ci ); - break; + if ( !mDelegate->hitContentItem() ) + { + // bleah + delete ci; + return; + } + idx = mDelegate->hitContentItemRight() ? \ + row->rightItems().indexOf( const_cast< Theme::ContentItem * >( mDelegate->hitContentItem() ) ) : \ + row->leftItems().indexOf( const_cast< Theme::ContentItem * >( mDelegate->hitContentItem() ) ); + if ( idx < 0 ) + { + // bleah + delete ci; + return; + } + if ( mDelegate->hitContentItemRight() ) + row->insertRightItem( idx+1, ci ); + else + row->insertLeftItem( idx, ci ); + break; case OnRightOfItem: - if ( !mDelegate->hitContentItem() ) - { - // bleah - delete ci; - return; - } - idx = mDelegate->hitContentItemRight() ? \ - row->rightItems().indexOf( const_cast< Theme::ContentItem * >( mDelegate->hitContentItem() ) ) : \ - row->leftItems().indexOf( const_cast< Theme::ContentItem * >( mDelegate->hitContentItem() ) ); - if ( idx < 0 ) - { - // bleah - delete ci; - return; - } - if ( mDelegate->hitContentItemRight() ) - row->insertRightItem( idx, ci ); - else - row->insertLeftItem( idx+1, ci ); - break; + if ( !mDelegate->hitContentItem() ) + { + // bleah + delete ci; + return; + } + idx = mDelegate->hitContentItemRight() ? \ + row->rightItems().indexOf( const_cast< Theme::ContentItem * >( mDelegate->hitContentItem() ) ) : \ + row->leftItems().indexOf( const_cast< Theme::ContentItem * >( mDelegate->hitContentItem() ) ); + if ( idx < 0 ) + { + // bleah + delete ci; + return; + } + if ( mDelegate->hitContentItemRight() ) + row->insertRightItem( idx, ci ); + else + row->insertLeftItem( idx+1, ci ); + break; case AsLastLeftItem: - row->addLeftItem( ci ); - break; + row->addLeftItem( ci ); + break; case AsLastRightItem: - row->addRightItem( ci ); - break; + row->addRightItem( ci ); + break; case AsFirstLeftItem: - row->insertLeftItem( 0, ci ); - break; + row->insertLeftItem( 0, ci ); + break; case AsFirstRightItem: - row->insertRightItem( 0, ci ); - break; + row->insertRightItem( 0, ci ); + break; default: // should never happen - row->addRightItem( ci ); - break; - } + row->addRightItem( ci ); + break; + } - e->acceptProposedAction(); + e->acceptProposedAction(); - mThemeSelectedContentItemRect = QRect(); - mDropIndicatorPoint1 = mDropIndicatorPoint2; - mSelectedThemeContentItem = 0; + mThemeSelectedContentItemRect = QRect(); + mDropIndicatorPoint1 = mDropIndicatorPoint2; + mSelectedThemeContentItem = 0; - setTheme( mTheme ); // this will reset theme cache and trigger a global update + setTheme( mTheme ); // this will reset theme cache and trigger a global update } bool ThemePreviewWidget::computeContentItemInsertPosition( const QPoint &pos, Theme::ContentItem::Type type ) { - mDropIndicatorPoint1 = mDropIndicatorPoint2; // this marks the position as invalid + mDropIndicatorPoint1 = mDropIndicatorPoint2; // this marks the position as invalid - if ( !mDelegate->hitTest( pos, false ) ) - return false; + if ( !mDelegate->hitTest( pos, false ) ) + return false; - if ( !mDelegate->hitRow() ) - return false; + if ( !mDelegate->hitRow() ) + return false; - if ( mDelegate->hitRowIsMessageRow() ) - { - if ( !Theme::ContentItem::applicableToMessageItems( type ) ) - return false; - } else { - if ( !Theme::ContentItem::applicableToGroupHeaderItems( type ) ) - return false; - } - - QRect rowRect = mDelegate->hitRowRect(); - - if ( pos.y() < rowRect.top() + 3 ) - { - // above a row - mRowInsertPosition = AboveRow; - if ( pos.x() < ( rowRect.left() + ( rowRect.width() / 2 ) ) ) + if ( mDelegate->hitRowIsMessageRow() ) { - mDropIndicatorPoint1 = rowRect.topLeft(); - mItemInsertPosition = AsLastLeftItem; + if ( !Theme::ContentItem::applicableToMessageItems( type ) ) + return false; } else { - mDropIndicatorPoint1 = rowRect.topRight(); - mItemInsertPosition = AsLastRightItem; + if ( !Theme::ContentItem::applicableToGroupHeaderItems( type ) ) + return false; } - mDropIndicatorPoint2 = QPoint( rowRect.left() + ( rowRect.width() / 2 ), rowRect.top() ); - return true; - } - if ( pos.y() > rowRect.bottom() - 3 ) - { - // below a row - mRowInsertPosition = BelowRow; - if ( pos.x() < ( rowRect.left() + ( rowRect.width() / 2 ) ) ) + QRect rowRect = mDelegate->hitRowRect(); + + if ( pos.y() < rowRect.top() + 3 ) { - mDropIndicatorPoint1 = rowRect.bottomLeft(); - mItemInsertPosition = AsLastLeftItem; - } else { - mDropIndicatorPoint1 = rowRect.bottomRight(); - mItemInsertPosition = AsLastRightItem; + // above a row + mRowInsertPosition = AboveRow; + if ( pos.x() < ( rowRect.left() + ( rowRect.width() / 2 ) ) ) + { + mDropIndicatorPoint1 = rowRect.topLeft(); + mItemInsertPosition = AsLastLeftItem; + } else { + mDropIndicatorPoint1 = rowRect.topRight(); + mItemInsertPosition = AsLastRightItem; + } + mDropIndicatorPoint2 = QPoint( rowRect.left() + ( rowRect.width() / 2 ), rowRect.top() ); + return true; + } + + if ( pos.y() > rowRect.bottom() - 3 ) + { + // below a row + mRowInsertPosition = BelowRow; + if ( pos.x() < ( rowRect.left() + ( rowRect.width() / 2 ) ) ) + { + mDropIndicatorPoint1 = rowRect.bottomLeft(); + mItemInsertPosition = AsLastLeftItem; + } else { + mDropIndicatorPoint1 = rowRect.bottomRight(); + mItemInsertPosition = AsLastRightItem; + } + mDropIndicatorPoint2 = QPoint( rowRect.left() + ( rowRect.width() / 2 ), rowRect.bottom() ); + return true; } - mDropIndicatorPoint2 = QPoint( rowRect.left() + ( rowRect.width() / 2 ), rowRect.bottom() ); - return true; - } - mRowInsertPosition = InsideRow; + mRowInsertPosition = InsideRow; - if ( !mDelegate->hitContentItem() ) - { - // didn't hit anything... probably no items in the row - if ( pos.x() < ( rowRect.left() + ( rowRect.width() / 2 ) ) ) - { - mItemInsertPosition = AsLastLeftItem; - mDropIndicatorPoint1 = QPoint( rowRect.left(), rowRect.top() ); - mDropIndicatorPoint2 = QPoint( rowRect.left(), rowRect.bottom() ); - } else { - mItemInsertPosition = AsLastRightItem; - mDropIndicatorPoint1 = QPoint( rowRect.right(), rowRect.top() ); - mDropIndicatorPoint2 = QPoint( rowRect.right(), rowRect.bottom() ); + if ( !mDelegate->hitContentItem() ) + { + // didn't hit anything... probably no items in the row + if ( pos.x() < ( rowRect.left() + ( rowRect.width() / 2 ) ) ) + { + mItemInsertPosition = AsLastLeftItem; + mDropIndicatorPoint1 = QPoint( rowRect.left(), rowRect.top() ); + mDropIndicatorPoint2 = QPoint( rowRect.left(), rowRect.bottom() ); + } else { + mItemInsertPosition = AsLastRightItem; + mDropIndicatorPoint1 = QPoint( rowRect.right(), rowRect.top() ); + mDropIndicatorPoint2 = QPoint( rowRect.right(), rowRect.bottom() ); + } + return true; } - return true; - } - // hit something, maybe inexactly - QRect itemRect = mDelegate->hitContentItemRect(); + // hit something, maybe inexactly + QRect itemRect = mDelegate->hitContentItemRect(); + + if ( !itemRect.contains( pos ) ) + { + // inexact hit: outside an item + if ( pos.x() > itemRect.right() ) + { + // right side of an item + if ( mDelegate->hitRow()->rightItems().count() < 1 ) + { + // between the last left item and the right side + if ( pos.x() > ( itemRect.right() + ( ( rowRect.right() - itemRect.right() ) / 2 ) ) ) + { + // first/last right item + mItemInsertPosition = AsFirstRightItem; + mDropIndicatorPoint1 = rowRect.topRight(); + mDropIndicatorPoint2 = rowRect.bottomRight(); + } + return true; + } + // either there were some right items (so the theme delegate knows that the reported item is the closest) + // or there were no right items but the position is closest to the left item than the right row end + mItemInsertPosition = OnRightOfItem; + mDropIndicatorPoint1 = itemRect.topRight(); + mDropIndicatorPoint2 = itemRect.bottomRight(); + return true; + } - if ( !itemRect.contains( pos ) ) - { - // inexact hit: outside an item - if ( pos.x() > itemRect.right() ) - { - // right side of an item - if ( mDelegate->hitRow()->rightItems().count() < 1 ) - { - // between the last left item and the right side - if ( pos.x() > ( itemRect.right() + ( ( rowRect.right() - itemRect.right() ) / 2 ) ) ) + // left side of an item + if ( mDelegate->hitRow()->leftItems().count() < 1 ) { - // first/last right item - mItemInsertPosition = AsFirstRightItem; - mDropIndicatorPoint1 = rowRect.topRight(); - mDropIndicatorPoint2 = rowRect.bottomRight(); + // between the left side and the leftmost right item + if ( pos.x() < ( itemRect.left() - ( ( itemRect.left() - rowRect.left() ) / 2 ) ) ) + { + mItemInsertPosition = AsFirstLeftItem; + mDropIndicatorPoint1 = rowRect.topLeft(); + mDropIndicatorPoint2 = rowRect.bottomLeft(); + return true; + } } + mItemInsertPosition = OnLeftOfItem; + mDropIndicatorPoint1 = itemRect.topLeft(); + mDropIndicatorPoint2 = itemRect.bottomLeft(); return true; - } - // either there were some right items (so the theme delegate knows that the reported item is the closest) - // or there were no right items but the position is closest to the left item than the right row end - mItemInsertPosition = OnRightOfItem; - mDropIndicatorPoint1 = itemRect.topRight(); - mDropIndicatorPoint2 = itemRect.bottomRight(); - return true; - } - - // left side of an item - if ( mDelegate->hitRow()->leftItems().count() < 1 ) - { - // between the left side and the leftmost right item - if ( pos.x() < ( itemRect.left() - ( ( itemRect.left() - rowRect.left() ) / 2 ) ) ) - { - mItemInsertPosition = AsFirstLeftItem; - mDropIndicatorPoint1 = rowRect.topLeft(); - mDropIndicatorPoint2 = rowRect.bottomLeft(); + } + + // exact hit + if ( pos.x() < ( itemRect.left() + ( itemRect.width() / 2 ) ) ) + { + // left side + mItemInsertPosition = OnLeftOfItem; + mDropIndicatorPoint1 = itemRect.topLeft(); + mDropIndicatorPoint2 = itemRect.bottomLeft(); return true; - } } - mItemInsertPosition = OnLeftOfItem; - mDropIndicatorPoint1 = itemRect.topLeft(); - mDropIndicatorPoint2 = itemRect.bottomLeft(); - return true; - } - // exact hit - if ( pos.x() < ( itemRect.left() + ( itemRect.width() / 2 ) ) ) - { - // left side - mItemInsertPosition = OnLeftOfItem; - mDropIndicatorPoint1 = itemRect.topLeft(); - mDropIndicatorPoint2 = itemRect.bottomLeft(); + // right side + mItemInsertPosition = OnRightOfItem; + mDropIndicatorPoint1 = itemRect.topRight(); + mDropIndicatorPoint2 = itemRect.bottomRight(); return true; - } - - // right side - mItemInsertPosition = OnRightOfItem; - mDropIndicatorPoint1 = itemRect.topRight(); - mDropIndicatorPoint2 = itemRect.bottomRight(); - return true; } void ThemePreviewWidget::mouseMoveEvent( QMouseEvent * e ) { - if ( ! ( mSelectedThemeContentItem && ( e->buttons() & Qt::LeftButton ) ) || mReadOnly ) - { - QTreeWidget::mouseMoveEvent( e ); - return; - } - - if ( mSelectedThemeContentItem != mDelegate->hitContentItem() ) - { - QTreeWidget::mouseMoveEvent( e ); - return; // ugh.. something weird happened - } - - // starting a drag ? - const QPoint diff = e->pos() - mMouseDownPoint; - if ( diff.manhattanLength() <= 4 ) - { - QTreeWidget::mouseMoveEvent( e ); - return; // ugh.. something weird happened - } - - // starting a drag - QMimeData * data = new QMimeData(); - QByteArray arry; - arry.resize( sizeof( Theme::ContentItem::Type ) ); - *( ( Theme::ContentItem::Type * ) arry.data() ) = mSelectedThemeContentItem->type(); - data->setData( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ), arry ); - QDrag * drag = new QDrag( this ); - drag->setMimeData( data ); - - // remove the Theme::ContentItem from the Theme - if ( mDelegate->hitContentItemRight() ) - const_cast< Theme::Row * >( mDelegate->hitRow() )->removeRightItem( mSelectedThemeContentItem ); - else - const_cast< Theme::Row * >( mDelegate->hitRow() )->removeLeftItem( mSelectedThemeContentItem ); - - delete mSelectedThemeContentItem; - - if ( mDelegate->hitRow()->rightItems().isEmpty() && mDelegate->hitRow()->leftItems().isEmpty() ) - { - if ( mDelegate->hitItem()->type() == Item::Message ) - { - if ( mDelegate->hitColumn()->messageRows().count() > 1 ) - { - const_cast< Theme::Column * >( mDelegate->hitColumn() )->removeMessageRow( const_cast< Theme::Row * >( mDelegate->hitRow() ) ); - delete mDelegate->hitRow(); - } - } else { - if ( mDelegate->hitColumn()->groupHeaderRows().count() > 1 ) - { - const_cast< Theme::Column * >( mDelegate->hitColumn() )->removeGroupHeaderRow( const_cast< Theme::Row * >( mDelegate->hitRow() ) ); - delete mDelegate->hitRow(); - } - } - } - - mSelectedThemeContentItem = 0; - mThemeSelectedContentItemRect = QRect(); - mDropIndicatorPoint1 = mDropIndicatorPoint2; + if ( ! ( mSelectedThemeContentItem && ( e->buttons() & Qt::LeftButton ) ) || mReadOnly ) + { + QTreeWidget::mouseMoveEvent( e ); + return; + } - setTheme( mTheme ); // this will reset theme cache and trigger a global update + if ( mSelectedThemeContentItem != mDelegate->hitContentItem() ) + { + QTreeWidget::mouseMoveEvent( e ); + return; // ugh.. something weird happened + } - // and do drag - drag->exec( Qt::CopyAction, Qt::CopyAction ); -} + // starting a drag ? + const QPoint diff = e->pos() - mMouseDownPoint; + if ( diff.manhattanLength() <= 4 ) + { + QTreeWidget::mouseMoveEvent( e ); + return; // ugh.. something weird happened + } -void ThemePreviewWidget::mousePressEvent( QMouseEvent * e ) -{ - if ( mReadOnly ) { - QTreeWidget::mousePressEvent( e ); - return; - } + // starting a drag + QMimeData * data = new QMimeData(); + QByteArray arry; + arry.resize( sizeof( Theme::ContentItem::Type ) ); + *( ( Theme::ContentItem::Type * ) arry.data() ) = mSelectedThemeContentItem->type(); + data->setData( QLatin1String( gThemeContentItemTypeDndMimeDataFormat ), arry ); + QDrag * drag = new QDrag( this ); + drag->setMimeData( data ); + + // remove the Theme::ContentItem from the Theme + if ( mDelegate->hitContentItemRight() ) + const_cast< Theme::Row * >( mDelegate->hitRow() )->removeRightItem( mSelectedThemeContentItem ); + else + const_cast< Theme::Row * >( mDelegate->hitRow() )->removeLeftItem( mSelectedThemeContentItem ); + + delete mSelectedThemeContentItem; - mMouseDownPoint = e->pos(); + if ( mDelegate->hitRow()->rightItems().isEmpty() && mDelegate->hitRow()->leftItems().isEmpty() ) + { + if ( mDelegate->hitItem()->type() == Item::Message ) + { + if ( mDelegate->hitColumn()->messageRows().count() > 1 ) + { + const_cast< Theme::Column * >( mDelegate->hitColumn() )->removeMessageRow( const_cast< Theme::Row * >( mDelegate->hitRow() ) ); + delete mDelegate->hitRow(); + } + } else { + if ( mDelegate->hitColumn()->groupHeaderRows().count() > 1 ) + { + const_cast< Theme::Column * >( mDelegate->hitColumn() )->removeGroupHeaderRow( const_cast< Theme::Row * >( mDelegate->hitRow() ) ); + delete mDelegate->hitRow(); + } + } + } - if ( mDelegate->hitTest( mMouseDownPoint ) ) - { - mSelectedThemeContentItem = const_cast< Theme::ContentItem * >( mDelegate->hitContentItem() ); - mThemeSelectedContentItemRect = mSelectedThemeContentItem ? mDelegate->hitContentItemRect() : QRect(); - } else { mSelectedThemeContentItem = 0; mThemeSelectedContentItemRect = QRect(); - } + mDropIndicatorPoint1 = mDropIndicatorPoint2; - QTreeWidget::mousePressEvent( e ); - viewport()->update(); + setTheme( mTheme ); // this will reset theme cache and trigger a global update - if ( e->button() == Qt::RightButton ) - { - KMenu menu; + // and do drag + drag->exec( Qt::CopyAction, Qt::CopyAction ); +} - if ( mSelectedThemeContentItem ) +void ThemePreviewWidget::mousePressEvent( QMouseEvent * e ) +{ + if ( mReadOnly ) { + QTreeWidget::mousePressEvent( e ); + return; + } + + mMouseDownPoint = e->pos(); + + if ( mDelegate->hitTest( mMouseDownPoint ) ) { + mSelectedThemeContentItem = const_cast< Theme::ContentItem * >( mDelegate->hitContentItem() ); + mThemeSelectedContentItemRect = mSelectedThemeContentItem ? mDelegate->hitContentItemRect() : QRect(); + } else { + mSelectedThemeContentItem = 0; + mThemeSelectedContentItemRect = QRect(); + } - menu.addTitle( Theme::ContentItem::description( mSelectedThemeContentItem->type() ) ); + QTreeWidget::mousePressEvent( e ); + viewport()->update(); - if ( mSelectedThemeContentItem->displaysText() ) - { - QAction * act; - act = menu.addAction( i18nc( "@action:inmenu soften the text color", "Soften" ) ); - act->setCheckable( true ); - act->setChecked( mSelectedThemeContentItem->softenByBlending() ); - connect( act, SIGNAL(triggered(bool)), - SLOT(slotSoftenActionTriggered(bool)) ); - - KMenu * childmenu = new KMenu( &menu ); - - QActionGroup * grp = new QActionGroup( childmenu ); - - act = childmenu->addAction( i18nc("@action:inmenu Font setting", "Default") ); - act->setData( QVariant( static_cast< int >( 0 ) ) ); - act->setCheckable( true ); - act->setChecked( !mSelectedThemeContentItem->useCustomFont() ); - grp->addAction( act ); - act = childmenu->addAction( i18nc("@action:inmenu Font setting", "Custom...") ); - act->setData( QVariant( static_cast< int >( Theme::ContentItem::UseCustomFont ) ) ); - act->setCheckable( true ); - act->setChecked( mSelectedThemeContentItem->useCustomFont() ); - grp->addAction( act ); - - - connect( childmenu, SIGNAL(triggered(QAction*)), - SLOT(slotFontMenuTriggered(QAction*)) ); - - menu.addMenu( childmenu )->setText( i18n( "Font" ) ); - } - - if ( mSelectedThemeContentItem->canUseCustomColor() ) - { - KMenu * childmenu = new KMenu( &menu ); - - QActionGroup * grp = new QActionGroup( childmenu ); - - QAction * act; - act = childmenu->addAction( i18nc("@action:inmenu Foreground color setting", "Default") ); - act->setData( QVariant( static_cast< int >( 0 ) ) ); - act->setCheckable( true ); - act->setChecked( !mSelectedThemeContentItem->useCustomColor() ); - grp->addAction( act ); - act = childmenu->addAction( i18nc("@action:inmenu Foreground color setting", "Custom...") ); - act->setData( QVariant( static_cast< int >( Theme::ContentItem::UseCustomColor ) ) ); - act->setCheckable( true ); - act->setChecked( mSelectedThemeContentItem->useCustomColor() ); - grp->addAction( act ); - - connect( childmenu, SIGNAL(triggered(QAction*)), - SLOT(slotForegroundColorMenuTriggered(QAction*)) ); - - menu.addMenu( childmenu )->setText( i18n( "Foreground Color" ) ); - } - - - if ( mSelectedThemeContentItem->canBeDisabled() ) - { - KMenu * childmenu = new KMenu( &menu ); - - QActionGroup * grp = new QActionGroup( childmenu ); - - QAction * act; - act = childmenu->addAction( i18nc("Hide a mark if the mail does not have the attribute, e.g. Important mark on a non important mail", "Hide") ); - act->setData( QVariant( static_cast< int >( Theme::ContentItem::HideWhenDisabled ) ) ); - act->setCheckable( true ); - act->setChecked( mSelectedThemeContentItem->hideWhenDisabled() ); - grp->addAction( act ); - act = childmenu->addAction( i18nc("Keep a empty space in the list if the mail does not have the attribute, e.g. Important mark on a non important mail", "Keep Empty Space") ); - act->setData( QVariant( static_cast< int >( 0 ) ) ); - act->setCheckable( true ); - act->setChecked( ! ( mSelectedThemeContentItem->softenByBlendingWhenDisabled() || mSelectedThemeContentItem->hideWhenDisabled() ) ); - grp->addAction( act ); - act = childmenu->addAction( i18nc("Show the icon softened in the list if the mail does not have the attribute, e.g. Important mark on a non important mail", "Keep Softened Icon") ); - act->setData( QVariant( static_cast< int >( Theme::ContentItem::SoftenByBlendingWhenDisabled ) ) ); - act->setCheckable( true ); - act->setChecked( mSelectedThemeContentItem->softenByBlendingWhenDisabled() ); - grp->addAction( act ); - - connect( childmenu, SIGNAL(triggered(QAction*)), - SLOT(slotDisabledFlagsMenuTriggered(QAction*)) ); - - menu.addMenu( childmenu )->setText( i18n( "When Disabled" ) ); - } - - } - - if ( mDelegate->hitItem() ) - { - if ( mDelegate->hitItem()->type() == Item::GroupHeader ) - { - menu.addTitle( i18n( "Group Header" ) ); - - // Background color (mode) submenu - KMenu * childmenu = new KMenu( &menu ); - - QActionGroup * grp = new QActionGroup( childmenu ); - - QAction * act; - act = childmenu->addAction( i18nc("@action:inmenu Group header background color setting", "None") ); - act->setData( QVariant( static_cast< int >( Theme::Transparent ) ) ); - act->setCheckable( true ); - act->setChecked( mTheme->groupHeaderBackgroundMode() == Theme::Transparent ); - grp->addAction( act ); - act = childmenu->addAction( i18nc("@action:inmenu Group header background color setting", "Automatic") ); - act->setData( QVariant( static_cast< int >( Theme::AutoColor ) ) ); - act->setCheckable( true ); - act->setChecked( mTheme->groupHeaderBackgroundMode() == Theme::AutoColor ); - grp->addAction( act ); - act = childmenu->addAction( i18nc("@action:inmenu Group header background color setting", "Custom...") ); - act->setData( QVariant( static_cast< int >( Theme::CustomColor ) ) ); - act->setCheckable( true ); - act->setChecked( mTheme->groupHeaderBackgroundMode() == Theme::CustomColor ); - grp->addAction( act ); - - - connect( childmenu, SIGNAL(triggered(QAction*)), - SLOT(slotGroupHeaderBackgroundModeMenuTriggered(QAction*)) ); - - menu.addMenu( childmenu )->setText( i18n( "Background Color" ) ); - - // Background style submenu - childmenu = new KMenu( &menu ); - - grp = new QActionGroup( childmenu ); - QList< QPair< QString, int > > styles = Theme::enumerateGroupHeaderBackgroundStyles(); - QList< QPair< QString, int > >::ConstIterator end( styles.constEnd() ); + if ( e->button() == Qt::RightButton ) + { + KMenu menu; - for ( QList< QPair< QString, int > >::ConstIterator it = styles.constBegin(); it != end; ++it ) + if ( mSelectedThemeContentItem ) { - act = childmenu->addAction( ( *it ).first ); - act->setData( QVariant( ( *it ).second ) ); - act->setCheckable( true ); - act->setChecked( mTheme->groupHeaderBackgroundStyle() == static_cast< Theme::GroupHeaderBackgroundStyle >( ( *it ).second ) ); - grp->addAction( act ); - } - connect( childmenu, SIGNAL(triggered(QAction*)), - SLOT(slotGroupHeaderBackgroundStyleMenuTriggered(QAction*)) ); + menu.addTitle( Theme::ContentItem::description( mSelectedThemeContentItem->type() ) ); - act = menu.addMenu( childmenu ); - act->setText( i18n( "Background Style" ) ); - if ( mTheme->groupHeaderBackgroundMode() == Theme::Transparent ) - act->setEnabled( false ); + if ( mSelectedThemeContentItem->displaysText() ) + { + QAction * act; + act = menu.addAction( i18nc( "@action:inmenu soften the text color", "Soften" ) ); + act->setCheckable( true ); + act->setChecked( mSelectedThemeContentItem->softenByBlending() ); + connect( act, SIGNAL(triggered(bool)), + SLOT(slotSoftenActionTriggered(bool)) ); + + KMenu * childmenu = new KMenu( &menu ); + + QActionGroup * grp = new QActionGroup( childmenu ); + + act = childmenu->addAction( i18nc("@action:inmenu Font setting", "Default") ); + act->setData( QVariant( static_cast< int >( 0 ) ) ); + act->setCheckable( true ); + act->setChecked( !mSelectedThemeContentItem->useCustomFont() ); + grp->addAction( act ); + act = childmenu->addAction( i18nc("@action:inmenu Font setting", "Custom...") ); + act->setData( QVariant( static_cast< int >( Theme::ContentItem::UseCustomFont ) ) ); + act->setCheckable( true ); + act->setChecked( mSelectedThemeContentItem->useCustomFont() ); + grp->addAction( act ); + + + connect( childmenu, SIGNAL(triggered(QAction*)), + SLOT(slotFontMenuTriggered(QAction*)) ); + + menu.addMenu( childmenu )->setText( i18n( "Font" ) ); + } + + if ( mSelectedThemeContentItem->canUseCustomColor() ) + { + KMenu * childmenu = new KMenu( &menu ); + + QActionGroup * grp = new QActionGroup( childmenu ); + + QAction * act; + act = childmenu->addAction( i18nc("@action:inmenu Foreground color setting", "Default") ); + act->setData( QVariant( static_cast< int >( 0 ) ) ); + act->setCheckable( true ); + act->setChecked( !mSelectedThemeContentItem->useCustomColor() ); + grp->addAction( act ); + act = childmenu->addAction( i18nc("@action:inmenu Foreground color setting", "Custom...") ); + act->setData( QVariant( static_cast< int >( Theme::ContentItem::UseCustomColor ) ) ); + act->setCheckable( true ); + act->setChecked( mSelectedThemeContentItem->useCustomColor() ); + grp->addAction( act ); + + connect( childmenu, SIGNAL(triggered(QAction*)), + SLOT(slotForegroundColorMenuTriggered(QAction*)) ); + + menu.addMenu( childmenu )->setText( i18n( "Foreground Color" ) ); + } + + + if ( mSelectedThemeContentItem->canBeDisabled() ) + { + KMenu * childmenu = new KMenu( &menu ); + + QActionGroup * grp = new QActionGroup( childmenu ); + + QAction * act; + act = childmenu->addAction( i18nc("Hide a mark if the mail does not have the attribute, e.g. Important mark on a non important mail", "Hide") ); + act->setData( QVariant( static_cast< int >( Theme::ContentItem::HideWhenDisabled ) ) ); + act->setCheckable( true ); + act->setChecked( mSelectedThemeContentItem->hideWhenDisabled() ); + grp->addAction( act ); + act = childmenu->addAction( i18nc("Keep a empty space in the list if the mail does not have the attribute, e.g. Important mark on a non important mail", "Keep Empty Space") ); + act->setData( QVariant( static_cast< int >( 0 ) ) ); + act->setCheckable( true ); + act->setChecked( ! ( mSelectedThemeContentItem->softenByBlendingWhenDisabled() || mSelectedThemeContentItem->hideWhenDisabled() ) ); + grp->addAction( act ); + act = childmenu->addAction( i18nc("Show the icon softened in the list if the mail does not have the attribute, e.g. Important mark on a non important mail", "Keep Softened Icon") ); + act->setData( QVariant( static_cast< int >( Theme::ContentItem::SoftenByBlendingWhenDisabled ) ) ); + act->setCheckable( true ); + act->setChecked( mSelectedThemeContentItem->softenByBlendingWhenDisabled() ); + grp->addAction( act ); - } - } + connect( childmenu, SIGNAL(triggered(QAction*)), + SLOT(slotDisabledFlagsMenuTriggered(QAction*)) ); + menu.addMenu( childmenu )->setText( i18n( "When Disabled" ) ); + } - if ( menu.isEmpty() ) - return; + } - menu.exec( viewport()->mapToGlobal( e->pos() ) ); + if ( mDelegate->hitItem() ) + { + if ( mDelegate->hitItem()->type() == Item::GroupHeader ) + { + menu.addTitle( i18n( "Group Header" ) ); + + // Background color (mode) submenu + KMenu * childmenu = new KMenu( &menu ); + + QActionGroup * grp = new QActionGroup( childmenu ); + + QAction * act; + act = childmenu->addAction( i18nc("@action:inmenu Group header background color setting", "None") ); + act->setData( QVariant( static_cast< int >( Theme::Transparent ) ) ); + act->setCheckable( true ); + act->setChecked( mTheme->groupHeaderBackgroundMode() == Theme::Transparent ); + grp->addAction( act ); + act = childmenu->addAction( i18nc("@action:inmenu Group header background color setting", "Automatic") ); + act->setData( QVariant( static_cast< int >( Theme::AutoColor ) ) ); + act->setCheckable( true ); + act->setChecked( mTheme->groupHeaderBackgroundMode() == Theme::AutoColor ); + grp->addAction( act ); + act = childmenu->addAction( i18nc("@action:inmenu Group header background color setting", "Custom...") ); + act->setData( QVariant( static_cast< int >( Theme::CustomColor ) ) ); + act->setCheckable( true ); + act->setChecked( mTheme->groupHeaderBackgroundMode() == Theme::CustomColor ); + grp->addAction( act ); + + + connect( childmenu, SIGNAL(triggered(QAction*)), + SLOT(slotGroupHeaderBackgroundModeMenuTriggered(QAction*)) ); + + menu.addMenu( childmenu )->setText( i18n( "Background Color" ) ); + + // Background style submenu + childmenu = new KMenu( &menu ); + + grp = new QActionGroup( childmenu ); + QList< QPair< QString, int > > styles = Theme::enumerateGroupHeaderBackgroundStyles(); + QList< QPair< QString, int > >::ConstIterator end( styles.constEnd() ); + + for ( QList< QPair< QString, int > >::ConstIterator it = styles.constBegin(); it != end; ++it ) + { + act = childmenu->addAction( ( *it ).first ); + act->setData( QVariant( ( *it ).second ) ); + act->setCheckable( true ); + act->setChecked( mTheme->groupHeaderBackgroundStyle() == static_cast< Theme::GroupHeaderBackgroundStyle >( ( *it ).second ) ); + grp->addAction( act ); + } + + connect( childmenu, SIGNAL(triggered(QAction*)), + SLOT(slotGroupHeaderBackgroundStyleMenuTriggered(QAction*)) ); + + act = menu.addMenu( childmenu ); + act->setText( i18n( "Background Style" ) ); + if ( mTheme->groupHeaderBackgroundMode() == Theme::Transparent ) + act->setEnabled( false ); + + } + } - } + + if ( menu.isEmpty() ) + return; + + menu.exec( viewport()->mapToGlobal( e->pos() ) ); + + } } void ThemePreviewWidget::slotDisabledFlagsMenuTriggered( QAction * act ) { - if ( !mSelectedThemeContentItem ) - return; + if ( !mSelectedThemeContentItem ) + return; - bool ok; - const int flags = act->data().toInt( &ok ); - if ( !ok ) - return; + bool ok; + const int flags = act->data().toInt( &ok ); + if ( !ok ) + return; - mSelectedThemeContentItem->setHideWhenDisabled( flags == Theme::ContentItem::HideWhenDisabled ); - mSelectedThemeContentItem->setSoftenByBlendingWhenDisabled( flags == Theme::ContentItem::SoftenByBlendingWhenDisabled ); + mSelectedThemeContentItem->setHideWhenDisabled( flags == Theme::ContentItem::HideWhenDisabled ); + mSelectedThemeContentItem->setSoftenByBlendingWhenDisabled( flags == Theme::ContentItem::SoftenByBlendingWhenDisabled ); - setTheme( mTheme ); // this will reset theme cache and trigger a global update + setTheme( mTheme ); // this will reset theme cache and trigger a global update } void ThemePreviewWidget::slotForegroundColorMenuTriggered( QAction * act ) { - if ( !mSelectedThemeContentItem ) - return; + if ( !mSelectedThemeContentItem ) + return; - bool ok; - const int flag = act->data().toInt( &ok ); - if ( !ok ) - return; - - if ( flag == 0 ) - { - mSelectedThemeContentItem->setUseCustomColor( false ); - setTheme( mTheme ); // this will reset theme cache and trigger a global update - return; - } + bool ok; + const int flag = act->data().toInt( &ok ); + if ( !ok ) + return; - QColor clr; - const int result = KColorDialog::getColor( clr, mSelectedThemeContentItem->customColor(), this ); - if ( result != KColorDialog::Accepted ) - return; + if ( flag == 0 ) + { + mSelectedThemeContentItem->setUseCustomColor( false ); + setTheme( mTheme ); // this will reset theme cache and trigger a global update + return; + } + + QColor clr; + const int result = KColorDialog::getColor( clr, mSelectedThemeContentItem->customColor(), this ); + if ( result != KColorDialog::Accepted ) + return; - mSelectedThemeContentItem->setCustomColor( clr ); - mSelectedThemeContentItem->setUseCustomColor( true ); + mSelectedThemeContentItem->setCustomColor( clr ); + mSelectedThemeContentItem->setUseCustomColor( true ); - setTheme( mTheme ); // this will reset theme cache and trigger a global update + setTheme( mTheme ); // this will reset theme cache and trigger a global update } void ThemePreviewWidget::slotSoftenActionTriggered( bool ) { - if ( !mSelectedThemeContentItem ) - return; + if ( !mSelectedThemeContentItem ) + return; - mSelectedThemeContentItem->setSoftenByBlending( !mSelectedThemeContentItem->softenByBlending() ); - setTheme( mTheme ); // this will reset theme cache and trigger a global update + mSelectedThemeContentItem->setSoftenByBlending( !mSelectedThemeContentItem->softenByBlending() ); + setTheme( mTheme ); // this will reset theme cache and trigger a global update } void ThemePreviewWidget::slotFontMenuTriggered( QAction * act ) { - if ( !mSelectedThemeContentItem ) - return; + if ( !mSelectedThemeContentItem ) + return; - bool ok; - const int flag = act->data().toInt( &ok ); - if ( !ok ) - return; - - if ( flag == 0 ) - { - mSelectedThemeContentItem->setUseCustomFont( false ); - setTheme( mTheme ); // this will reset theme cache and trigger a global update - return; - } + bool ok; + const int flag = act->data().toInt( &ok ); + if ( !ok ) + return; - QFont f = mSelectedThemeContentItem->font(); - if ( KFontDialog::getFont( f ) != KFontDialog::Accepted ) - return; + if ( flag == 0 ) + { + mSelectedThemeContentItem->setUseCustomFont( false ); + setTheme( mTheme ); // this will reset theme cache and trigger a global update + return; + } + + QFont f = mSelectedThemeContentItem->font(); + if ( KFontDialog::getFont( f ) != KFontDialog::Accepted ) + return; - mSelectedThemeContentItem->setFont( f ); - mSelectedThemeContentItem->setUseCustomFont( true ); + mSelectedThemeContentItem->setFont( f ); + mSelectedThemeContentItem->setUseCustomFont( true ); - setTheme( mTheme ); // this will reset theme cache and trigger a global update + setTheme( mTheme ); // this will reset theme cache and trigger a global update } void ThemePreviewWidget::slotGroupHeaderBackgroundModeMenuTriggered( QAction * act ) { - bool ok; - Theme::GroupHeaderBackgroundMode mode = static_cast< Theme::GroupHeaderBackgroundMode >( act->data().toInt( &ok ) ); - if ( !ok ) - return; + bool ok; + Theme::GroupHeaderBackgroundMode mode = static_cast< Theme::GroupHeaderBackgroundMode >( act->data().toInt( &ok ) ); + if ( !ok ) + return; - switch( mode ) - { + switch( mode ) + { case Theme::Transparent: - mTheme->setGroupHeaderBackgroundMode( Theme::Transparent ); - break; + mTheme->setGroupHeaderBackgroundMode( Theme::Transparent ); + break; case Theme::AutoColor: - mTheme->setGroupHeaderBackgroundMode( Theme::AutoColor ); - break; + mTheme->setGroupHeaderBackgroundMode( Theme::AutoColor ); + break; case Theme::CustomColor: { - QColor clr; - int result = KColorDialog::getColor( clr, mTheme->groupHeaderBackgroundColor(), this ); - if ( result != KColorDialog::Accepted ) - return; + QColor clr; + int result = KColorDialog::getColor( clr, mTheme->groupHeaderBackgroundColor(), this ); + if ( result != KColorDialog::Accepted ) + return; - mTheme->setGroupHeaderBackgroundMode( Theme::CustomColor ); - mTheme->setGroupHeaderBackgroundColor( clr ); + mTheme->setGroupHeaderBackgroundMode( Theme::CustomColor ); + mTheme->setGroupHeaderBackgroundColor( clr ); + } + break; } - break; - } - setTheme( mTheme ); // this will reset theme cache and trigger a global update + setTheme( mTheme ); // this will reset theme cache and trigger a global update } void ThemePreviewWidget::slotGroupHeaderBackgroundStyleMenuTriggered( QAction * act ) { - bool ok; - Theme::GroupHeaderBackgroundStyle mode = static_cast< Theme::GroupHeaderBackgroundStyle >( act->data().toInt( &ok ) ); - if ( !ok ) - return; + bool ok; + Theme::GroupHeaderBackgroundStyle mode = static_cast< Theme::GroupHeaderBackgroundStyle >( act->data().toInt( &ok ) ); + if ( !ok ) + return; - mTheme->setGroupHeaderBackgroundStyle( mode ); + mTheme->setGroupHeaderBackgroundStyle( mode ); - setTheme( mTheme ); // this will reset theme cache and trigger a global update + setTheme( mTheme ); // this will reset theme cache and trigger a global update } void ThemePreviewWidget::paintEvent( QPaintEvent * e ) { - QTreeWidget::paintEvent( e ); + QTreeWidget::paintEvent( e ); - if ( - mThemeSelectedContentItemRect.isValid() || - ( mDropIndicatorPoint1 != mDropIndicatorPoint2 ) - ) - { - QPainter painter( viewport() ); - - if ( mThemeSelectedContentItemRect.isValid() ) - { - painter.setPen( QPen( Qt::black ) ); - painter.drawRect( mThemeSelectedContentItemRect ); - } - if ( mDropIndicatorPoint1 != mDropIndicatorPoint2 ) + if ( + mThemeSelectedContentItemRect.isValid() || + ( mDropIndicatorPoint1 != mDropIndicatorPoint2 ) + ) { - painter.setPen( QPen( Qt::black, 3 ) ); - painter.drawLine( mDropIndicatorPoint1, mDropIndicatorPoint2 ); + QPainter painter( viewport() ); + + if ( mThemeSelectedContentItemRect.isValid() ) + { + painter.setPen( QPen( Qt::black ) ); + painter.drawRect( mThemeSelectedContentItemRect ); + } + if ( mDropIndicatorPoint1 != mDropIndicatorPoint2 ) + { + painter.setPen( QPen( Qt::black, 3 ) ); + painter.drawLine( mDropIndicatorPoint1, mDropIndicatorPoint2 ); + } } - } } void ThemePreviewWidget::slotHeaderContextMenuRequested( const QPoint &pos ) { - if ( mReadOnly ) - return; + if ( mReadOnly ) + return; - QTreeWidgetItem * hitem = headerItem(); - if ( !hitem ) - return; // ooops + QTreeWidgetItem * hitem = headerItem(); + if ( !hitem ) + return; // ooops - int col = header()->logicalIndexAt( pos ); + int col = header()->logicalIndexAt( pos ); - if ( col < 0 ) - return; + if ( col < 0 ) + return; - if ( col >= mTheme->columns().count() ) - return; + if ( col >= mTheme->columns().count() ) + return; - mSelectedThemeColumn = mTheme->column( col ); - if ( !mSelectedThemeColumn ) - return; + mSelectedThemeColumn = mTheme->column( col ); + if ( !mSelectedThemeColumn ) + return; - KMenu menu; + KMenu menu; - menu.addTitle( mSelectedThemeColumn->label() ); + menu.addTitle( mSelectedThemeColumn->label() ); - QAction * act; + QAction * act; - act = menu.addAction( i18n( "Column Properties..." ) ); - connect( act, SIGNAL(triggered(bool)), - SLOT(slotColumnProperties()) ); + act = menu.addAction( i18n( "Column Properties..." ) ); + connect( act, SIGNAL(triggered(bool)), + SLOT(slotColumnProperties()) ); - act = menu.addAction( i18n( "Add Column..." ) ); - connect( act, SIGNAL(triggered(bool)), - SLOT(slotAddColumn()) ); + act = menu.addAction( i18n( "Add Column..." ) ); + connect( act, SIGNAL(triggered(bool)), + SLOT(slotAddColumn()) ); - act = menu.addAction( i18n( "Delete Column" ) ); - connect( act, SIGNAL(triggered(bool)), - SLOT(slotDeleteColumn()) ); - act->setEnabled( col > 0 ); + act = menu.addAction( i18n( "Delete Column" ) ); + connect( act, SIGNAL(triggered(bool)), + SLOT(slotDeleteColumn()) ); + act->setEnabled( col > 0 ); - menu.addSeparator(); + menu.addSeparator(); - act = menu.addAction( i18n( "Move Column to Left")); - connect( act, SIGNAL(triggered(bool)), - SLOT(slotMoveColumnToLeft()) ); - act->setEnabled( col > 0 ); + act = menu.addAction( i18n( "Move Column to Left")); + connect( act, SIGNAL(triggered(bool)), + SLOT(slotMoveColumnToLeft()) ); + act->setEnabled( col > 0 ); - act = menu.addAction( i18n( "Move Column to Right")); - connect( act, SIGNAL(triggered(bool)), - SLOT(slotMoveColumnToRight()) ); - act->setEnabled( col < mTheme->columns().count()-1 ); + act = menu.addAction( i18n( "Move Column to Right")); + connect( act, SIGNAL(triggered(bool)), + SLOT(slotMoveColumnToRight()) ); + act->setEnabled( col < mTheme->columns().count()-1 ); - menu.exec( header()->mapToGlobal( pos ) ); + menu.exec( header()->mapToGlobal( pos ) ); } void ThemePreviewWidget::slotMoveColumnToLeft() { - if ( !mSelectedThemeColumn ) - return; + if ( !mSelectedThemeColumn ) + return; - const int columnIndex = mTheme->columns().indexOf( mSelectedThemeColumn ); - mTheme->moveColumn(columnIndex, columnIndex -1); - setTheme( mTheme ); // this will reset theme cache and trigger a global update + const int columnIndex = mTheme->columns().indexOf( mSelectedThemeColumn ); + mTheme->moveColumn(columnIndex, columnIndex -1); + setTheme( mTheme ); // this will reset theme cache and trigger a global update } void ThemePreviewWidget::slotMoveColumnToRight() { - if ( !mSelectedThemeColumn ) - return; + if ( !mSelectedThemeColumn ) + return; - const int columnIndex = mTheme->columns().indexOf( mSelectedThemeColumn ); - mTheme->moveColumn(columnIndex, columnIndex +1); - setTheme( mTheme ); // this will reset theme cache and trigger a global update + const int columnIndex = mTheme->columns().indexOf( mSelectedThemeColumn ); + mTheme->moveColumn(columnIndex, columnIndex +1); + setTheme( mTheme ); // this will reset theme cache and trigger a global update } void ThemePreviewWidget::slotAddColumn() { - int newColumnIndex = mTheme->columns().count(); + int newColumnIndex = mTheme->columns().count(); - if ( mSelectedThemeColumn ) - { - newColumnIndex = mTheme->columns().indexOf( mSelectedThemeColumn ); - if ( newColumnIndex < 0 ) - newColumnIndex = mTheme->columns().count(); - else - newColumnIndex++; - } + if ( mSelectedThemeColumn ) + { + newColumnIndex = mTheme->columns().indexOf( mSelectedThemeColumn ); + if ( newColumnIndex < 0 ) + newColumnIndex = mTheme->columns().count(); + else + newColumnIndex++; + } - mSelectedThemeColumn = new Theme::Column(); - mSelectedThemeColumn->setLabel( i18n( "New Column" ) ); - mSelectedThemeColumn->setVisibleByDefault( true ); - - mSelectedThemeColumn->addMessageRow( new Theme::Row() ); - mSelectedThemeColumn->addGroupHeaderRow( new Theme::Row() ); - - ThemeColumnPropertiesDialog* dlg = - new ThemeColumnPropertiesDialog( this, mSelectedThemeColumn, i18n( "Add New Column" ) ); - - if ( dlg->exec() == QDialog::Accepted ) - { - mTheme->insertColumn( newColumnIndex, mSelectedThemeColumn ); + mSelectedThemeColumn = new Theme::Column(); + mSelectedThemeColumn->setLabel( i18n( "New Column" ) ); + mSelectedThemeColumn->setVisibleByDefault( true ); - mSelectedThemeContentItem = 0; - mThemeSelectedContentItemRect = QRect(); - mDropIndicatorPoint1 = mDropIndicatorPoint2; + mSelectedThemeColumn->addMessageRow( new Theme::Row() ); + mSelectedThemeColumn->addGroupHeaderRow( new Theme::Row() ); - setTheme( mTheme ); // this will reset theme cache and trigger a global update + ThemeColumnPropertiesDialog* dlg = + new ThemeColumnPropertiesDialog( this, mSelectedThemeColumn, i18n( "Add New Column" ) ); - } else { + if ( dlg->exec() == QDialog::Accepted ) + { + mTheme->insertColumn( newColumnIndex, mSelectedThemeColumn ); - delete mSelectedThemeColumn; - mSelectedThemeColumn = 0; - } + mSelectedThemeContentItem = 0; + mThemeSelectedContentItemRect = QRect(); + mDropIndicatorPoint1 = mDropIndicatorPoint2; + + setTheme( mTheme ); // this will reset theme cache and trigger a global update + + } else { - delete dlg; + delete mSelectedThemeColumn; + mSelectedThemeColumn = 0; + } + + delete dlg; } void ThemePreviewWidget::slotColumnProperties() { - if ( !mSelectedThemeColumn ) - return; + if ( !mSelectedThemeColumn ) + return; - ThemeColumnPropertiesDialog *dlg = - new ThemeColumnPropertiesDialog( this, mSelectedThemeColumn, i18n( "Column Properties" ) ); + ThemeColumnPropertiesDialog *dlg = + new ThemeColumnPropertiesDialog( this, mSelectedThemeColumn, i18n( "Column Properties" ) ); - if ( dlg->exec() == QDialog::Accepted ) - { - mSelectedThemeContentItem = 0; - mThemeSelectedContentItemRect = QRect(); - mDropIndicatorPoint1 = mDropIndicatorPoint2; + if ( dlg->exec() == QDialog::Accepted ) + { + mSelectedThemeContentItem = 0; + mThemeSelectedContentItemRect = QRect(); + mDropIndicatorPoint1 = mDropIndicatorPoint2; - setTheme( mTheme ); // this will reset theme cache and trigger a global update - } + setTheme( mTheme ); // this will reset theme cache and trigger a global update + } - delete dlg; + delete dlg; } void ThemePreviewWidget::slotDeleteColumn() { - if ( !mSelectedThemeColumn ) - return; + if ( !mSelectedThemeColumn ) + return; + + const int idx = mTheme->columns().indexOf( mSelectedThemeColumn ); + if ( idx < 1 ) // first column can't be deleted + return; + + mTheme->removeColumn( mSelectedThemeColumn ); + delete mSelectedThemeColumn; + mSelectedThemeColumn = 0; - const int idx = mTheme->columns().indexOf( mSelectedThemeColumn ); - if ( idx < 1 ) // first column can't be deleted - return; - - mTheme->removeColumn( mSelectedThemeColumn ); - delete mSelectedThemeColumn; - mSelectedThemeColumn = 0; - - mSelectedThemeContentItem = 0; - mThemeSelectedContentItemRect = QRect(); - mDropIndicatorPoint1 = mDropIndicatorPoint2; + mSelectedThemeContentItem = 0; + mThemeSelectedContentItemRect = QRect(); + mDropIndicatorPoint1 = mDropIndicatorPoint2; - setTheme( mTheme ); // this will reset theme cache and trigger a global update + setTheme( mTheme ); // this will reset theme cache and trigger a global update } @@ -1351,195 +1351,195 @@ ThemeEditor::ThemeEditor( QWidget *parent ) - : OptionSetEditor( parent ) + : OptionSetEditor( parent ) { - mCurrentTheme = 0; + mCurrentTheme = 0; - // Appearance tab - QWidget * tab = new QWidget( this ); - addTab( tab, i18n( "Appearance" ) ); + // Appearance tab + QWidget * tab = new QWidget( this ); + addTab( tab, i18n( "Appearance" ) ); - QGridLayout * tabg = new QGridLayout( tab ); + QGridLayout * tabg = new QGridLayout( tab ); - QGroupBox * gb = new QGroupBox( i18n( "Content Items" ), tab ); - tabg->addWidget( gb, 0, 0 ); + QGroupBox * gb = new QGroupBox( i18n( "Content Items" ), tab ); + tabg->addWidget( gb, 0, 0 ); - QGridLayout * gblayout = new QGridLayout( gb ); + QGridLayout * gblayout = new QGridLayout( gb ); - ThemeContentItemSourceLabel * cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::Subject ); - cil->setText( Theme::ContentItem::description( cil->type() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 0, 0 ); + ThemeContentItemSourceLabel * cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::Subject ); + cil->setText( Theme::ContentItem::description( cil->type() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 0, 0 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::Date ); - cil->setText( Theme::ContentItem::description( cil->type() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 1, 0 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::Date ); + cil->setText( Theme::ContentItem::description( cil->type() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 1, 0 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::Size ); - cil->setText( Theme::ContentItem::description( cil->type() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 2, 0 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::Size ); + cil->setText( Theme::ContentItem::description( cil->type() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 2, 0 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::Sender ); - cil->setText( Theme::ContentItem::description( cil->type() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 0, 1 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::Sender ); + cil->setText( Theme::ContentItem::description( cil->type() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 0, 1 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::Receiver ); - cil->setText( Theme::ContentItem::description( cil->type() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 1, 1 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::Receiver ); + cil->setText( Theme::ContentItem::description( cil->type() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 1, 1 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::SenderOrReceiver ); - cil->setText( Theme::ContentItem::description( cil->type() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 2, 1 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::SenderOrReceiver ); + cil->setText( Theme::ContentItem::description( cil->type() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 2, 1 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::MostRecentDate ); - cil->setText( Theme::ContentItem::description( cil->type() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 0, 2 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::MostRecentDate ); + cil->setText( Theme::ContentItem::description( cil->type() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 0, 2 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::TagList ); - cil->setText( Theme::ContentItem::description( cil->type() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 1, 2 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::TagList ); + cil->setText( Theme::ContentItem::description( cil->type() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 1, 2 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::CombinedReadRepliedStateIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageRepliedAndForwarded() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 0, 3 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::CombinedReadRepliedStateIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageRepliedAndForwarded() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 0, 3 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::ReadStateIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageNew() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 1, 3 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::ReadStateIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageNew() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 1, 3 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::RepliedStateIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageReplied() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 2, 3 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::RepliedStateIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageReplied() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 2, 3 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::AttachmentStateIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageAttachment() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 0, 4 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::AttachmentStateIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageAttachment() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 0, 4 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::EncryptionStateIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageFullyEncrypted() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 1, 4 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::EncryptionStateIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageFullyEncrypted() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 1, 4 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::SignatureStateIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageFullySigned() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 2, 4 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::SignatureStateIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageFullySigned() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 2, 4 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::ActionItemStateIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageActionItem() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 0, 5 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::ActionItemStateIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageActionItem() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 0, 5 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::AnnotationIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageAnnotation() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 1, 5 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::AnnotationIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageAnnotation() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 1, 5 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::InvitationIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageInvitation() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 2, 5 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::InvitationIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageInvitation() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 2, 5 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::ImportantStateIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageImportant() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 0, 6 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::ImportantStateIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageImportant() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 0, 6 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::SpamHamStateIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageSpam() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 1, 6 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::SpamHamStateIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageSpam() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 1, 6 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::WatchedIgnoredStateIcon ); - cil->setPixmap( *( Manager::instance()->pixmapMessageWatched() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 2, 6 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::WatchedIgnoredStateIcon ); + cil->setPixmap( *( Manager::instance()->pixmapMessageWatched() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 2, 6 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::ExpandedStateIcon ); - cil->setPixmap( *( Manager::instance()->pixmapShowMore() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 0, 7 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::ExpandedStateIcon ); + cil->setPixmap( *( Manager::instance()->pixmapShowMore() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 0, 7 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::VerticalLine ); - cil->setPixmap( *( Manager::instance()->pixmapVerticalLine() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 1, 7 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::VerticalLine ); + cil->setPixmap( *( Manager::instance()->pixmapVerticalLine() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 1, 7 ); - cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::HorizontalSpacer ); - cil->setPixmap( *( Manager::instance()->pixmapHorizontalSpacer() ) ); - cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); - gblayout->addWidget( cil, 2, 7 ); + cil = new ThemeContentItemSourceLabel( gb, Theme::ContentItem::HorizontalSpacer ); + cil->setPixmap( *( Manager::instance()->pixmapHorizontalSpacer() ) ); + cil->setToolTip( Theme::ContentItem::description( cil->type() ) ); + gblayout->addWidget( cil, 2, 7 ); - mPreviewWidget = new ThemePreviewWidget( tab ); - tabg->addWidget( mPreviewWidget, 1, 0 ); + mPreviewWidget = new ThemePreviewWidget( tab ); + tabg->addWidget( mPreviewWidget, 1, 0 ); - QLabel * l = new QLabel( tab ); - l->setText( i18n( "Right click on the header to add or modify columns. Drag the content items and drop them on the columns in order to compose your theme. Right click on the items inside the view for more options." ) ); - l->setWordWrap( true ); - l->setAlignment( Qt::AlignCenter ); - tabg->addWidget( l, 2, 0 ); + QLabel * l = new QLabel( tab ); + l->setText( i18n( "Right click on the header to add or modify columns. Drag the content items and drop them on the columns in order to compose your theme. Right click on the items inside the view for more options." ) ); + l->setWordWrap( true ); + l->setAlignment( Qt::AlignCenter ); + tabg->addWidget( l, 2, 0 ); - tabg->setRowStretch( 1, 1 ); + tabg->setRowStretch( 1, 1 ); - // Advanced tab - tab = new QWidget( this ); - addTab( tab, i18nc( "@title:tab Advanced theme settings", "Advanced" ) ); + // Advanced tab + tab = new QWidget( this ); + addTab( tab, i18nc( "@title:tab Advanced theme settings", "Advanced" ) ); - tabg = new QGridLayout( tab ); + tabg = new QGridLayout( tab ); - l = new QLabel( i18n( "Header:" ), tab ); - tabg->addWidget( l, 0, 0 ); + l = new QLabel( i18n( "Header:" ), tab ); + tabg->addWidget( l, 0, 0 ); - mViewHeaderPolicyCombo = new KComboBox( tab ); - tabg->addWidget( mViewHeaderPolicyCombo, 0, 1 ); + mViewHeaderPolicyCombo = new KComboBox( tab ); + tabg->addWidget( mViewHeaderPolicyCombo, 0, 1 ); - l = new QLabel( i18n( "Icon size:" ), tab ); - tabg->addWidget( l, 1, 0 ); + l = new QLabel( i18n( "Icon size:" ), tab ); + tabg->addWidget( l, 1, 0 ); - mIconSizeSpinBox = new KIntSpinBox( tab ); - mIconSizeSpinBox->setMinimum( 8 ); - mIconSizeSpinBox->setMaximum( 64 ); - mIconSizeSpinBox->setSuffix( ki18ncp( "suffix in a spinbox", " pixel", " pixels" ) ); + mIconSizeSpinBox = new KIntSpinBox( tab ); + mIconSizeSpinBox->setMinimum( 8 ); + mIconSizeSpinBox->setMaximum( 64 ); + mIconSizeSpinBox->setSuffix( ki18ncp( "suffix in a spinbox", " pixel", " pixels" ) ); - QObject::connect( - mIconSizeSpinBox, SIGNAL(valueChanged(int)), - this, SLOT(slotIconSizeSpinBoxValueChanged(int)) - ); + QObject::connect( + mIconSizeSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(slotIconSizeSpinBoxValueChanged(int)) + ); - tabg->addWidget( mIconSizeSpinBox, 1, 1 ); + tabg->addWidget( mIconSizeSpinBox, 1, 1 ); - tabg->setColumnStretch( 1, 1 ); - tabg->setRowStretch( 2, 1 ); - fillViewHeaderPolicyCombo(); + tabg->setColumnStretch( 1, 1 ); + tabg->setRowStretch( 2, 1 ); + fillViewHeaderPolicyCombo(); } @@ -1549,71 +1549,71 @@ void ThemeEditor::editTheme( Theme *set ) { - mCurrentTheme = set; - mPreviewWidget->setTheme(mCurrentTheme); - - if ( !mCurrentTheme ) - { - setEnabled( false ); - return; - } - setEnabled( true ); + mCurrentTheme = set; + mPreviewWidget->setTheme(mCurrentTheme); - nameEdit()->setText( set->name() ); - descriptionEdit()->setPlainText( set->description() ); + if ( !mCurrentTheme ) + { + setEnabled( false ); + return; + } + setEnabled( true ); + + nameEdit()->setText( set->name() ); + descriptionEdit()->setPlainText( set->description() ); - ComboBoxUtils::setIntegerOptionComboValue( mViewHeaderPolicyCombo, (int)mCurrentTheme->viewHeaderPolicy() ); + ComboBoxUtils::setIntegerOptionComboValue( mViewHeaderPolicyCombo, (int)mCurrentTheme->viewHeaderPolicy() ); - mIconSizeSpinBox->setValue( set->iconSize() ); - setReadOnly( mCurrentTheme->readOnly() ); + mIconSizeSpinBox->setValue( set->iconSize() ); + setReadOnly( mCurrentTheme->readOnly() ); } void ThemeEditor::setReadOnly( bool readOnly ) { - mPreviewWidget->setReadOnly( readOnly ); - mViewHeaderPolicyCombo->setEnabled( !readOnly ); - mIconSizeSpinBox->setEnabled( !readOnly ); - OptionSetEditor::setReadOnly( readOnly ); + mPreviewWidget->setReadOnly( readOnly ); + mViewHeaderPolicyCombo->setEnabled( !readOnly ); + mIconSizeSpinBox->setEnabled( !readOnly ); + OptionSetEditor::setReadOnly( readOnly ); } void ThemeEditor::commit() { - if ( !mCurrentTheme || mCurrentTheme->readOnly() ) - return; + if ( !mCurrentTheme || mCurrentTheme->readOnly() ) + return; - mCurrentTheme->setName( nameEdit()->text() ); - mCurrentTheme->setDescription( descriptionEdit()->toPlainText() ); + mCurrentTheme->setName( nameEdit()->text() ); + mCurrentTheme->setDescription( descriptionEdit()->toPlainText() ); - mCurrentTheme->setViewHeaderPolicy( - (Theme::ViewHeaderPolicy)ComboBoxUtils::getIntegerOptionComboValue( mViewHeaderPolicyCombo, 0 ) - ); - mCurrentTheme->setIconSize( mIconSizeSpinBox->value() ); - // other settings are already committed to this theme + mCurrentTheme->setViewHeaderPolicy( + (Theme::ViewHeaderPolicy)ComboBoxUtils::getIntegerOptionComboValue( mViewHeaderPolicyCombo, 0 ) + ); + mCurrentTheme->setIconSize( mIconSizeSpinBox->value() ); + // other settings are already committed to this theme } void ThemeEditor::fillViewHeaderPolicyCombo() { - ComboBoxUtils::fillIntegerOptionCombo( - mViewHeaderPolicyCombo, - Theme::enumerateViewHeaderPolicyOptions() - ); + ComboBoxUtils::fillIntegerOptionCombo( + mViewHeaderPolicyCombo, + Theme::enumerateViewHeaderPolicyOptions() + ); } void ThemeEditor::slotNameEditTextEdited( const QString &newName ) { - if( !mCurrentTheme ) - return; - mCurrentTheme->setName( newName ); - emit themeNameChanged(); + if( !mCurrentTheme ) + return; + mCurrentTheme->setName( newName ); + emit themeNameChanged(); } void ThemeEditor::slotIconSizeSpinBoxValueChanged( int val ) { - if( !mCurrentTheme ) - return; - mCurrentTheme->setIconSize( val ); + if( !mCurrentTheme ) + return; + mCurrentTheme->setIconSize( val ); - mPreviewWidget->setTheme( mCurrentTheme ); // will trigger a cache reset and a view update + mPreviewWidget->setTheme( mCurrentTheme ); // will trigger a cache reset and a view update } MessageList::Core::Theme *ThemeEditor::editedTheme() const diff -Nru kdepim-4.12.97/messagelist/utils/themeeditor.h kdepim-4.13.0/messagelist/utils/themeeditor.h --- kdepim-4.12.97/messagelist/utils/themeeditor.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/utils/themeeditor.h 2014-04-10 07:40:20.000000000 +0000 @@ -57,187 +57,187 @@ class ThemeColumnPropertiesDialog : public KDialog { - Q_OBJECT + Q_OBJECT public: - explicit ThemeColumnPropertiesDialog( QWidget * parent, Core::Theme::Column * column, const QString &title ); + explicit ThemeColumnPropertiesDialog( QWidget * parent, Core::Theme::Column * column, const QString &title ); protected: - Core::Theme::Column * mColumn; - KLineEdit * mNameEdit; - QCheckBox * mVisibleByDefaultCheck; - QCheckBox * mIsSenderOrReceiverCheck; - KComboBox * mMessageSortingCombo; + Core::Theme::Column * mColumn; + KLineEdit * mNameEdit; + QCheckBox * mVisibleByDefaultCheck; + QCheckBox * mIsSenderOrReceiverCheck; + KComboBox * mMessageSortingCombo; protected slots: - void slotOkButtonClicked(); + void slotOkButtonClicked(); }; class ThemePreviewDelegate : public Core::ThemeDelegate { - Q_OBJECT + Q_OBJECT public: - explicit ThemePreviewDelegate( QAbstractItemView * parent ); - ~ThemePreviewDelegate(); + explicit ThemePreviewDelegate( QAbstractItemView * parent ); + ~ThemePreviewDelegate(); private: - Core::GroupHeaderItem * mSampleGroupHeaderItem; - Core::FakeItem * mSampleMessageItem; - Core::ModelInvariantRowMapper * mRowMapper; // needed for the MessageItem above to be valid + Core::GroupHeaderItem * mSampleGroupHeaderItem; + Core::FakeItem * mSampleMessageItem; + Core::ModelInvariantRowMapper * mRowMapper; // needed for the MessageItem above to be valid public: - virtual Core::Item * itemFromIndex( const QModelIndex &index ) const; + virtual Core::Item * itemFromIndex( const QModelIndex &index ) const; }; class ThemePreviewWidget : public QTreeWidget { - Q_OBJECT + Q_OBJECT public: - explicit ThemePreviewWidget( QWidget * parent ); - ~ThemePreviewWidget(); - void setReadOnly( bool readOnly); + explicit ThemePreviewWidget( QWidget * parent ); + ~ThemePreviewWidget(); + void setReadOnly( bool readOnly); private: - // DnD insert position stuff + // DnD insert position stuff - /** + /** * The row we'll be inserting the dragged item into */ - enum RowInsertPosition - { - AboveRow, ///< We'll insert above the currently hit row in mDelegate - InsideRow, ///< We'll insert inside the currently hit row in mDelegate - BelowRow ///< We'll insert below the currently hit row in mDelegate - }; + enum RowInsertPosition + { + AboveRow, ///< We'll insert above the currently hit row in mDelegate + InsideRow, ///< We'll insert inside the currently hit row in mDelegate + BelowRow ///< We'll insert below the currently hit row in mDelegate + }; - /** + /** * The position in row that we'll be inserting the dragged item */ - enum ItemInsertPosition - { - OnLeftOfItem, ///< We'll insert on the left of the selected item - OnRightOfItem, ///< We'll insert on the right of the selected item - AsLastLeftItem, ///< We'll insert as last left item of the row (rightmost left item) - AsLastRightItem, ///< We'll insert as last right item of the row (leftmost right item) - AsFirstLeftItem, ///< We'll insert as first left item of the row (leftmost) - AsFirstRightItem ///< We'll insert as first right item of the row (rightmost) - }; - -private: - ThemePreviewDelegate * mDelegate; - QTreeWidgetItem * mGroupHeaderSampleItem; - QRect mThemeSelectedContentItemRect; - Core::Theme::ContentItem * mSelectedThemeContentItem; - Core::Theme::Column * mSelectedThemeColumn; - QPoint mMouseDownPoint; - Core::Theme * mTheme; - RowInsertPosition mRowInsertPosition; - ItemInsertPosition mItemInsertPosition; - QPoint mDropIndicatorPoint1; - QPoint mDropIndicatorPoint2; - bool mFirstShow; - bool mReadOnly; + enum ItemInsertPosition + { + OnLeftOfItem, ///< We'll insert on the left of the selected item + OnRightOfItem, ///< We'll insert on the right of the selected item + AsLastLeftItem, ///< We'll insert as last left item of the row (rightmost left item) + AsLastRightItem, ///< We'll insert as last right item of the row (leftmost right item) + AsFirstLeftItem, ///< We'll insert as first left item of the row (leftmost) + AsFirstRightItem ///< We'll insert as first right item of the row (rightmost) + }; + +private: + ThemePreviewDelegate * mDelegate; + QTreeWidgetItem * mGroupHeaderSampleItem; + QRect mThemeSelectedContentItemRect; + Core::Theme::ContentItem * mSelectedThemeContentItem; + Core::Theme::Column * mSelectedThemeColumn; + QPoint mMouseDownPoint; + Core::Theme * mTheme; + RowInsertPosition mRowInsertPosition; + ItemInsertPosition mItemInsertPosition; + QPoint mDropIndicatorPoint1; + QPoint mDropIndicatorPoint2; + bool mFirstShow; + bool mReadOnly; public: - QSize sizeHint() const; - void setTheme( Core::Theme * theme ); + QSize sizeHint() const; + void setTheme( Core::Theme * theme ); protected: - virtual void dragMoveEvent( QDragMoveEvent * e ); - virtual void dragEnterEvent( QDragEnterEvent * e ); - virtual void dropEvent( QDropEvent * e ); - virtual void mouseMoveEvent( QMouseEvent * e ); - virtual void mousePressEvent( QMouseEvent * e ); - virtual void paintEvent( QPaintEvent * e ); - virtual void showEvent( QShowEvent * e ); + virtual void dragMoveEvent( QDragMoveEvent * e ); + virtual void dragEnterEvent( QDragEnterEvent * e ); + virtual void dropEvent( QDropEvent * e ); + virtual void mouseMoveEvent( QMouseEvent * e ); + virtual void mousePressEvent( QMouseEvent * e ); + virtual void paintEvent( QPaintEvent * e ); + virtual void showEvent( QShowEvent * e ); private: - void internalHandleDragMoveEvent( QDragMoveEvent * e ); - void internalHandleDragEnterEvent( QDragEnterEvent * e ); + void internalHandleDragMoveEvent( QDragMoveEvent * e ); + void internalHandleDragEnterEvent( QDragEnterEvent * e ); - /** + /** * Computes the drop insert position for the dragged item at position pos. * Returns true if the dragged item can be inserted somewhere and * false otherwise. Sets mRowInsertPosition, mItemInsertPosition, * mDropIndicatorPoint1 ,mDropIndicatorPoint2. */ - bool computeContentItemInsertPosition( const QPoint &pos, Core::Theme::ContentItem::Type type ); + bool computeContentItemInsertPosition( const QPoint &pos, Core::Theme::ContentItem::Type type ); - void applyThemeColumnWidths(); + void applyThemeColumnWidths(); protected slots: - void slotHeaderContextMenuRequested( const QPoint &pos ); - void slotAddColumn(); - void slotColumnProperties(); - void slotDeleteColumn(); - void slotDisabledFlagsMenuTriggered( QAction * act ); - void slotForegroundColorMenuTriggered( QAction * act ); - void slotFontMenuTriggered( QAction * act ); - void slotSoftenActionTriggered( bool ); - void slotGroupHeaderBackgroundModeMenuTriggered( QAction * act ); - void slotGroupHeaderBackgroundStyleMenuTriggered( QAction * act ); - void slotMoveColumnToLeft(); - void slotMoveColumnToRight(); + void slotHeaderContextMenuRequested( const QPoint &pos ); + void slotAddColumn(); + void slotColumnProperties(); + void slotDeleteColumn(); + void slotDisabledFlagsMenuTriggered( QAction * act ); + void slotForegroundColorMenuTriggered( QAction * act ); + void slotFontMenuTriggered( QAction * act ); + void slotSoftenActionTriggered( bool ); + void slotGroupHeaderBackgroundModeMenuTriggered( QAction * act ); + void slotGroupHeaderBackgroundStyleMenuTriggered( QAction * act ); + void slotMoveColumnToLeft(); + void slotMoveColumnToRight(); }; class ThemeContentItemSourceLabel : public QLabel { - Q_OBJECT + Q_OBJECT public: - ThemeContentItemSourceLabel( QWidget * parent, Core::Theme::ContentItem::Type type ); - ~ThemeContentItemSourceLabel(); + ThemeContentItemSourceLabel( QWidget * parent, Core::Theme::ContentItem::Type type ); + ~ThemeContentItemSourceLabel(); public: - Core::Theme::ContentItem::Type type() const; - void startDrag(); + Core::Theme::ContentItem::Type type() const; + void startDrag(); protected: - void mousePressEvent( QMouseEvent * e ); - void mouseMoveEvent( QMouseEvent * e ); + void mousePressEvent( QMouseEvent * e ); + void mouseMoveEvent( QMouseEvent * e ); private: - Core::Theme::ContentItem::Type mType; - QPoint mMousePressPoint; + Core::Theme::ContentItem::Type mType; + QPoint mMousePressPoint; }; class ThemeEditor : public OptionSetEditor { - Q_OBJECT + Q_OBJECT public: - explicit ThemeEditor( QWidget *parent ); - ~ThemeEditor(); + explicit ThemeEditor( QWidget *parent ); + ~ThemeEditor(); public: - /** + /** * Sets the option set to be edited. * Saves and forgets any previously option set that was being edited. * The set parameter may be 0: in this case the editor is simply disabled. */ - void editTheme( Core::Theme *set ); + void editTheme( Core::Theme *set ); - Core::Theme * editedTheme() const; + Core::Theme * editedTheme() const; - void commit(); + void commit(); signals: - void themeNameChanged(); + void themeNameChanged(); private: - void fillViewHeaderPolicyCombo(); + void fillViewHeaderPolicyCombo(); protected slots: - void slotNameEditTextEdited( const QString &newName ); - void slotIconSizeSpinBoxValueChanged( int val ); + void slotNameEditTextEdited( const QString &newName ); + void slotIconSizeSpinBoxValueChanged( int val ); private: - void setReadOnly( bool readOnly ); + void setReadOnly( bool readOnly ); - Core::Theme * mCurrentTheme; // shallow, may be null! + Core::Theme * mCurrentTheme; // shallow, may be null! - // Appearance tab - ThemePreviewWidget * mPreviewWidget; + // Appearance tab + ThemePreviewWidget * mPreviewWidget; - // Advanced tab - KComboBox * mViewHeaderPolicyCombo; - KIntSpinBox * mIconSizeSpinBox; + // Advanced tab + KComboBox * mViewHeaderPolicyCombo; + KIntSpinBox * mIconSizeSpinBox; }; } // namespace Utils diff -Nru kdepim-4.12.97/messagelist/widget.cpp kdepim-4.13.0/messagelist/widget.cpp --- kdepim-4.12.97/messagelist/widget.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/widget.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -61,19 +61,19 @@ class Widget::Private { public: - Private( Widget *owner ) - : q( owner ), mLastSelectedMessage(-1), mXmlGuiClient( 0 ) { } + Private( Widget *owner ) + : q( owner ), mLastSelectedMessage(-1), mXmlGuiClient( 0 ) { } - Akonadi::Item::List selectionAsItems() const; - Akonadi::Item itemForRow( int row ) const; - KMime::Message::Ptr messageForRow( int row ) const; - - Widget * const q; - - int mLastSelectedMessage; - KXMLGUIClient *mXmlGuiClient; - QModelIndex mGroupHeaderItemIndex; - Akonadi::Monitor *mMonitor; + Akonadi::Item::List selectionAsItems() const; + Akonadi::Item itemForRow( int row ) const; + KMime::Message::Ptr messageForRow( int row ) const; + + Widget * const q; + + int mLastSelectedMessage; + KXMLGUIClient *mXmlGuiClient; + QModelIndex mGroupHeaderItemIndex; + Akonadi::Monitor *mMonitor; }; } // namespace MessageList @@ -82,55 +82,55 @@ using namespace Akonadi; Widget::Widget( QWidget *parent ) - : Core::Widget( parent ), d( new Private( this ) ) + : Core::Widget( parent ), d( new Private( this ) ) { - populateStatusFilterCombo(); + populateStatusFilterCombo(); - d->mMonitor = new Akonadi::Monitor( this ); - d->mMonitor->setTypeMonitored( Akonadi::Monitor::Tags ); - connect(d->mMonitor, SIGNAL(tagAdded(Akonadi::Tag)), this, SLOT(populateStatusFilterCombo())); - connect(d->mMonitor, SIGNAL(tagRemoved(Akonadi::Tag)), this, SLOT(populateStatusFilterCombo())); - connect(d->mMonitor, SIGNAL(tagChanged(Akonadi::Tag)), this, SLOT(populateStatusFilterCombo())); + d->mMonitor = new Akonadi::Monitor( this ); + d->mMonitor->setTypeMonitored( Akonadi::Monitor::Tags ); + connect(d->mMonitor, SIGNAL(tagAdded(Akonadi::Tag)), this, SLOT(populateStatusFilterCombo())); + connect(d->mMonitor, SIGNAL(tagRemoved(Akonadi::Tag)), this, SLOT(populateStatusFilterCombo())); + connect(d->mMonitor, SIGNAL(tagChanged(Akonadi::Tag)), this, SLOT(populateStatusFilterCombo())); } Widget::~Widget() { - delete d; + delete d; } void Widget::setXmlGuiClient( KXMLGUIClient *xmlGuiClient ) { - d->mXmlGuiClient = xmlGuiClient; + d->mXmlGuiClient = xmlGuiClient; } bool Widget::canAcceptDrag( const QDropEvent * e ) { - if ( e->source() == view()->viewport() ) - return false; - - Collection::List collections = static_cast( storageModel() )->displayedCollections(); - if ( collections.size()!=1 ) - return false; // no folder here or too many (in case we can't decide where the drop will end) - - const Collection target = collections.first(); - - if ( ( target.rights() & Collection::CanCreateItem ) == 0 ) - return false; // no way to drag into - - const KUrl::List urls = KUrl::List::fromMimeData( e->mimeData() ); - foreach ( const KUrl &url, urls ) { - const Collection collection = Collection::fromUrl( url ); - if ( collection.isValid() ) { // You're not supposed to drop collections here - return false; - } else { // Yay, this is an item! - const QString type = url.queryItems()[QLatin1String( "type" )]; // But does it have the right type? - if ( !target.contentMimeTypes().contains( type ) ) { + if ( e->source() == view()->viewport() ) return false; - } + + Collection::List collections = static_cast( storageModel() )->displayedCollections(); + if ( collections.size()!=1 ) + return false; // no folder here or too many (in case we can't decide where the drop will end) + + const Collection target = collections.first(); + + if ( ( target.rights() & Collection::CanCreateItem ) == 0 ) + return false; // no way to drag into + + const KUrl::List urls = KUrl::List::fromMimeData( e->mimeData() ); + foreach ( const KUrl &url, urls ) { + const Collection collection = Collection::fromUrl( url ); + if ( collection.isValid() ) { // You're not supposed to drop collections here + return false; + } else { // Yay, this is an item! + const QString type = url.queryItems()[QLatin1String( "type" )]; // But does it have the right type? + if ( !target.contentMimeTypes().contains( type ) ) { + return false; + } + } } - } - return true; + return true; } bool Widget::selectNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, @@ -138,7 +138,7 @@ bool centerItem, bool loop ) { - return view()->selectNextMessageItem( messageTypeFilter, existingSelectionBehaviour, centerItem, loop ); + return view()->selectNextMessageItem( messageTypeFilter, existingSelectionBehaviour, centerItem, loop ); } bool Widget::selectPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, @@ -146,604 +146,604 @@ bool centerItem, bool loop ) { - return view()->selectPreviousMessageItem( messageTypeFilter, existingSelectionBehaviour, centerItem, loop ); + return view()->selectPreviousMessageItem( messageTypeFilter, existingSelectionBehaviour, centerItem, loop ); } bool Widget::focusNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ) { - return view()->focusNextMessageItem( messageTypeFilter, centerItem, loop ); + return view()->focusNextMessageItem( messageTypeFilter, centerItem, loop ); } bool Widget::focusPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ) { - return view()->focusPreviousMessageItem( messageTypeFilter, centerItem, loop ); + return view()->focusPreviousMessageItem( messageTypeFilter, centerItem, loop ); } void Widget::selectFocusedMessageItem( bool centerItem ) { - view()->selectFocusedMessageItem( centerItem ); + view()->selectFocusedMessageItem( centerItem ); } bool Widget::selectFirstMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem ) { - return view()->selectFirstMessageItem( messageTypeFilter, centerItem ); + return view()->selectFirstMessageItem( messageTypeFilter, centerItem ); } bool Widget::selectLastMessageItem( Core::MessageTypeFilter messageTypeFilter, bool centerItem ) { - return view()->selectLastMessageItem( messageTypeFilter, centerItem ); + return view()->selectLastMessageItem( messageTypeFilter, centerItem ); } void Widget::selectAll() { - view()->setAllGroupsExpanded( true ); - view()->selectAll(); + view()->setAllGroupsExpanded( true ); + view()->selectAll(); } void Widget::setCurrentThreadExpanded( bool expand ) { - view()->setCurrentThreadExpanded(expand ); + view()->setCurrentThreadExpanded(expand ); } void Widget::setAllThreadsExpanded( bool expand ) { - view()->setAllThreadsExpanded( expand ); + view()->setAllThreadsExpanded( expand ); } void Widget::setAllGroupsExpanded( bool expand ) { - view()->setAllGroupsExpanded(expand); + view()->setAllGroupsExpanded(expand); } void Widget::focusQuickSearch() { - view()->focusQuickSearch(); + view()->focusQuickSearch(); } void Widget::setQuickSearchClickMessage(const QString &msg) { - view()->setQuickSearchClickMessage(msg); + view()->setQuickSearchClickMessage(msg); } void Widget::fillMessageTagCombo() { - Akonadi::TagFetchJob *fetchJob = new Akonadi::TagFetchJob(this); - fetchJob->fetchScope().fetchAttribute(); - connect(fetchJob, SIGNAL(result(KJob*)), this, SLOT(slotTagsFetched(KJob*))); + Akonadi::TagFetchJob *fetchJob = new Akonadi::TagFetchJob(this); + fetchJob->fetchScope().fetchAttribute(); + connect(fetchJob, SIGNAL(result(KJob*)), this, SLOT(slotTagsFetched(KJob*))); } void Widget::slotTagsFetched(KJob *job) { - if (job->error()) { - kWarning() << "Failed to load tags " << job->errorString(); - return; - } - Akonadi::TagFetchJob *fetchJob = static_cast(job); - - KConfigGroup conf( MessageList::Core::Settings::self()->config(),"MessageListView"); - const QString tagSelected= conf.readEntry(QLatin1String("TagSelected")); - if(tagSelected.isEmpty()) { - setCurrentStatusFilterItem(); - return; - } - const QStringList tagSelectedLst = tagSelected.split(QLatin1Char(',')); - - addMessageTagItem( SmallIcon( QLatin1String( "mail-flag" ) ), i18n( "All" ), QString() ); - - QStringList tagFound; - foreach( const Akonadi::Tag &akonadiTag, fetchJob->tags() ) { - if(tagSelectedLst.contains(akonadiTag.url().url())) { - tagFound.append(akonadiTag.url().url()); - QString iconName = QLatin1String( "mail-tagged" ); - const QString label = akonadiTag.name(); - const QString id = akonadiTag.url().url(); - Akonadi::TagAttribute *attr = akonadiTag.attribute(); - if (attr) { - iconName = attr->iconName(); - } - addMessageTagItem( SmallIcon( iconName ), label, QVariant( id ) ); - } - } - conf.writeEntry(QLatin1String("TagSelected"), tagFound); - conf.sync(); + if (job->error()) { + kWarning() << "Failed to load tags " << job->errorString(); + return; + } + Akonadi::TagFetchJob *fetchJob = static_cast(job); + + KConfigGroup conf( MessageList::Core::Settings::self()->config(),"MessageListView"); + const QString tagSelected= conf.readEntry(QLatin1String("TagSelected")); + if(tagSelected.isEmpty()) { + setCurrentStatusFilterItem(); + return; + } + const QStringList tagSelectedLst = tagSelected.split(QLatin1Char(',')); + + addMessageTagItem( SmallIcon( QLatin1String( "mail-flag" ) ), i18n( "All" ), QString() ); - setCurrentStatusFilterItem(); + QStringList tagFound; + foreach( const Akonadi::Tag &akonadiTag, fetchJob->tags() ) { + if(tagSelectedLst.contains(akonadiTag.url().url())) { + tagFound.append(akonadiTag.url().url()); + QString iconName = QLatin1String( "mail-tagged" ); + const QString label = akonadiTag.name(); + const QString id = akonadiTag.url().url(); + Akonadi::TagAttribute *attr = akonadiTag.attribute(); + if (attr) { + iconName = attr->iconName(); + } + addMessageTagItem( SmallIcon( iconName ), label, QVariant( id ) ); + } + } + conf.writeEntry(QLatin1String("TagSelected"), tagFound); + conf.sync(); + + setCurrentStatusFilterItem(); } void Widget::viewMessageSelected( MessageList::Core::MessageItem *msg ) { - int row = -1; - if ( msg ) { - row = msg->currentModelIndexRow(); - } - - if ( !msg || !msg->isValid() || !storageModel() ) { - d->mLastSelectedMessage = -1; - emit messageSelected( Item() ); - return; - } + int row = -1; + if ( msg ) { + row = msg->currentModelIndexRow(); + } + + if ( !msg || !msg->isValid() || !storageModel() ) { + d->mLastSelectedMessage = -1; + emit messageSelected( Item() ); + return; + } - Q_ASSERT( row >= 0 ); + Q_ASSERT( row >= 0 ); - d->mLastSelectedMessage = row; + d->mLastSelectedMessage = row; - emit messageSelected( d->itemForRow( row ) ); // this MAY be null + emit messageSelected( d->itemForRow( row ) ); // this MAY be null } void Widget::viewMessageActivated( MessageList::Core::MessageItem *msg ) { - Q_ASSERT( msg ); // must not be null - Q_ASSERT( storageModel() ); + Q_ASSERT( msg ); // must not be null + Q_ASSERT( storageModel() ); + + if ( !msg->isValid() ) { + return; + } - if ( !msg->isValid() ) { - return; - } - - int row = msg->currentModelIndexRow(); - Q_ASSERT( row >= 0 ); - - // The assert below may fail when quickly opening and closing a non-selected thread. - // This will actually activate the item without selecting it... - //Q_ASSERT( d->mLastSelectedMessage == row ); - - if ( d->mLastSelectedMessage != row ) { - // Very ugly. We are activating a non selected message. - // This is very likely a double click on the plus sign near a thread leader. - // Dealing with mLastSelectedMessage here would be expensive: it would involve releasing the last selected, - // emitting signals, handling recursion... ugly. - // We choose a very simple solution: double clicking on the plus sign near a thread leader does - // NOT activate the message (i.e open it in a toplevel window) if it isn't previously selected. - return; - } + int row = msg->currentModelIndexRow(); + Q_ASSERT( row >= 0 ); - emit messageActivated( d->itemForRow( row ) ); // this MAY be null + // The assert below may fail when quickly opening and closing a non-selected thread. + // This will actually activate the item without selecting it... + //Q_ASSERT( d->mLastSelectedMessage == row ); + + if ( d->mLastSelectedMessage != row ) { + // Very ugly. We are activating a non selected message. + // This is very likely a double click on the plus sign near a thread leader. + // Dealing with mLastSelectedMessage here would be expensive: it would involve releasing the last selected, + // emitting signals, handling recursion... ugly. + // We choose a very simple solution: double clicking on the plus sign near a thread leader does + // NOT activate the message (i.e open it in a toplevel window) if it isn't previously selected. + return; + } + + emit messageActivated( d->itemForRow( row ) ); // this MAY be null } void Widget::viewSelectionChanged() { - emit selectionChanged(); - if ( !currentMessageItem() ) { - emit messageSelected( Item() ); - } + emit selectionChanged(); + if ( !currentMessageItem() ) { + emit messageSelected( Item() ); + } } void Widget::viewMessageListContextPopupRequest( const QList< MessageList::Core::MessageItem * > &selectedItems, const QPoint &globalPos ) { - Q_UNUSED( selectedItems ); + Q_UNUSED( selectedItems ); - if ( !d->mXmlGuiClient ) - return; + if ( !d->mXmlGuiClient ) + return; - QMenu *popup = static_cast( d->mXmlGuiClient->factory()->container( - QLatin1String( "akonadi_messagelist_contextmenu" ), - d->mXmlGuiClient ) ); - if ( popup ) { - popup->exec( globalPos ); - } + QMenu *popup = static_cast( d->mXmlGuiClient->factory()->container( + QLatin1String( "akonadi_messagelist_contextmenu" ), + d->mXmlGuiClient ) ); + if ( popup ) { + popup->exec( globalPos ); + } } void Widget::viewMessageStatusChangeRequest( MessageList::Core::MessageItem *msg, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear ) { - Q_ASSERT( msg ); // must not be null - Q_ASSERT( storageModel() ); + Q_ASSERT( msg ); // must not be null + Q_ASSERT( storageModel() ); - if ( !msg->isValid() ) { - return; - } + if ( !msg->isValid() ) { + return; + } - int row = msg->currentModelIndexRow(); - Q_ASSERT( row >= 0 ); + int row = msg->currentModelIndexRow(); + Q_ASSERT( row >= 0 ); - Item item = d->itemForRow( row ); - Q_ASSERT( item.isValid() ); + Item item = d->itemForRow( row ); + Q_ASSERT( item.isValid() ); - emit messageStatusChangeRequest( item, set, clear ); + emit messageStatusChangeRequest( item, set, clear ); } void Widget::viewGroupHeaderContextPopupRequest( MessageList::Core::GroupHeaderItem *ghi, const QPoint &globalPos ) { - Q_UNUSED( ghi ); + Q_UNUSED( ghi ); + + KMenu menu( this ); + + QAction *act; - KMenu menu( this ); + QModelIndex index = view()->model()->index( ghi, 0 ); + d->mGroupHeaderItemIndex = index; - QAction *act; + if ( view()->isExpanded( index ) ) { + act = menu.addAction( i18n ( "Collapse Group" ) ); + connect( act, SIGNAL(triggered(bool)), + this, SLOT(slotCollapseItem()) ); + } else { + act = menu.addAction( i18n ( "Expand Group" ) ); + connect( act, SIGNAL(triggered(bool)), + this, SLOT(slotExpandItem()) ); + } - QModelIndex index = view()->model()->index( ghi, 0 ); - d->mGroupHeaderItemIndex = index; + menu.addSeparator(); - if ( view()->isExpanded( index ) ) { - act = menu.addAction( i18n ( "Collapse Group" ) ); + act = menu.addAction( i18n( "Expand All Groups" ) ); connect( act, SIGNAL(triggered(bool)), - this, SLOT(slotCollapseItem()) ); - } else { - act = menu.addAction( i18n ( "Expand Group" ) ); + view(), SLOT(slotExpandAllGroups()) ); + + act = menu.addAction( i18n( "Collapse All Groups" ) ); connect( act, SIGNAL(triggered(bool)), - this, SLOT(slotExpandItem()) ); - } - - menu.addSeparator(); - - act = menu.addAction( i18n( "Expand All Groups" ) ); - connect( act, SIGNAL(triggered(bool)), - view(), SLOT(slotExpandAllGroups()) ); - - act = menu.addAction( i18n( "Collapse All Groups" ) ); - connect( act, SIGNAL(triggered(bool)), - view(), SLOT(slotCollapseAllGroups()) ); + view(), SLOT(slotCollapseAllGroups()) ); - menu.exec( globalPos ); + menu.exec( globalPos ); } void Widget::viewDragEnterEvent( QDragEnterEvent *e ) { - if ( !canAcceptDrag( e ) ) { - e->ignore(); - return; - } + if ( !canAcceptDrag( e ) ) { + e->ignore(); + return; + } - e->accept(); + e->accept(); } void Widget::viewDragMoveEvent( QDragMoveEvent *e ) { - if ( !canAcceptDrag( e ) ) { - e->ignore(); - return; - } + if ( !canAcceptDrag( e ) ) { + e->ignore(); + return; + } - e->accept(); + e->accept(); } enum DragMode { - DragCopy, - DragMove, - DragCancel + DragCopy, + DragMove, + DragCancel }; void Widget::viewDropEvent( QDropEvent *e ) { - if ( !canAcceptDrag( e ) ) { - e->ignore(); - return; - } - - KUrl::List urls = KUrl::List::fromMimeData( e->mimeData() ); - if ( urls.isEmpty() ) { - kWarning() << "Could not decode drag data!"; - e->ignore(); - return; - } - - e->accept(); - - int action; - if ( ( e->possibleActions() & Qt::MoveAction ) == 0 ) { // We can't move anyway - action = DragCopy; - } else { - action = DragCancel; - int keybstate = QApplication::keyboardModifiers(); - if ( keybstate & Qt::CTRL ) { - action = DragCopy; + if ( !canAcceptDrag( e ) ) { + e->ignore(); + return; + } - } else if ( keybstate & Qt::SHIFT ) { - action = DragMove; + KUrl::List urls = KUrl::List::fromMimeData( e->mimeData() ); + if ( urls.isEmpty() ) { + kWarning() << "Could not decode drag data!"; + e->ignore(); + return; + } - } else { - KMenu menu; - QAction *moveAction = menu.addAction( KIcon( QLatin1String( "go-jump" )), i18n( "&Move Here" ) ); - QAction *copyAction = menu.addAction( KIcon( QLatin1String( "edit-copy" ) ), i18n( "&Copy Here" ) ); - menu.addSeparator(); - menu.addAction( KIcon( QLatin1String( "dialog-cancel" ) ), i18n( "C&ancel" ) ); - - QAction *menuChoice = menu.exec( QCursor::pos() ); - if ( menuChoice == moveAction ) { - action = DragMove; - } else if ( menuChoice == copyAction ) { + e->accept(); + + int action; + if ( ( e->possibleActions() & Qt::MoveAction ) == 0 ) { // We can't move anyway action = DragCopy; - } else { + } else { action = DragCancel; - } + int keybstate = QApplication::keyboardModifiers(); + if ( keybstate & Qt::CTRL ) { + action = DragCopy; + + } else if ( keybstate & Qt::SHIFT ) { + action = DragMove; + + } else { + KMenu menu; + QAction *moveAction = menu.addAction( KIcon( QLatin1String( "go-jump" )), i18n( "&Move Here" ) ); + QAction *copyAction = menu.addAction( KIcon( QLatin1String( "edit-copy" ) ), i18n( "&Copy Here" ) ); + menu.addSeparator(); + menu.addAction( KIcon( QLatin1String( "dialog-cancel" ) ), i18n( "C&ancel" ) ); + + QAction *menuChoice = menu.exec( QCursor::pos() ); + if ( menuChoice == moveAction ) { + action = DragMove; + } else if ( menuChoice == copyAction ) { + action = DragCopy; + } else { + action = DragCancel; + } + } + } + if ( action == DragCancel ) + return; + + Collection::List collections = static_cast( storageModel() )->displayedCollections(); + Collection target = collections.first(); + Item::List items; + foreach ( const KUrl &url, urls ) { + items << Item::fromUrl( url ); + } + + if ( action == DragCopy ) { + new ItemCopyJob( items, target, this ); + } else if ( action == DragMove ) { + new ItemMoveJob( items, target, this ); } - } - if ( action == DragCancel ) - return; - - Collection::List collections = static_cast( storageModel() )->displayedCollections(); - Collection target = collections.first(); - Item::List items; - foreach ( const KUrl &url, urls ) { - items << Item::fromUrl( url ); - } - - if ( action == DragCopy ) { - new ItemCopyJob( items, target, this ); - } else if ( action == DragMove ) { - new ItemMoveJob( items, target, this ); - } } void Widget::viewStartDragRequest() { - Collection::List collections = static_cast( storageModel() )->displayedCollections(); + Collection::List collections = static_cast( storageModel() )->displayedCollections(); - if ( collections.isEmpty() ) - return; // no folder here + if ( collections.isEmpty() ) + return; // no folder here - QList items = d->selectionAsItems(); - if ( items.isEmpty() ) - return; - - bool readOnly = false; - - foreach ( const Collection &c, collections ) { - // We won't be able to remove items from this collection - if ( ( c.rights() & Collection::CanDeleteItem ) == 0 ) { - // So the drag will be read-only - readOnly = true; - break; - } - } - - KUrl::List urls; - foreach ( const Item &i, items ) { - urls << i.url( Item::UrlWithMimeType ); - } - - QMimeData *mimeData = new QMimeData; - urls.populateMimeData( mimeData ); - - QDrag *drag = new QDrag( view()->viewport() ); - drag->setMimeData( mimeData ); - - // Set pixmap - QPixmap pixmap; - if( items.size() == 1 ) { - pixmap = QPixmap( DesktopIcon(QLatin1String( "mail-message" ), KIconLoader::SizeSmall) ); - } else { - pixmap = QPixmap( DesktopIcon(QLatin1String( "document-multiple" ), KIconLoader::SizeSmall) ); - } - - // Calculate hotspot (as in Konqueror) - if( !pixmap.isNull() ) { - drag->setHotSpot( QPoint( pixmap.width() / 2, pixmap.height() / 2 ) ); - drag->setPixmap( pixmap ); - } - - if ( readOnly ) - drag->exec( Qt::CopyAction ); - else - drag->exec( Qt::CopyAction | Qt::MoveAction ); + QList items = d->selectionAsItems(); + if ( items.isEmpty() ) + return; + + bool readOnly = false; + + foreach ( const Collection &c, collections ) { + // We won't be able to remove items from this collection + if ( ( c.rights() & Collection::CanDeleteItem ) == 0 ) { + // So the drag will be read-only + readOnly = true; + break; + } + } + + KUrl::List urls; + foreach ( const Item &i, items ) { + urls << i.url( Item::UrlWithMimeType ); + } + + QMimeData *mimeData = new QMimeData; + urls.populateMimeData( mimeData ); + + QDrag *drag = new QDrag( view()->viewport() ); + drag->setMimeData( mimeData ); + + // Set pixmap + QPixmap pixmap; + if( items.size() == 1 ) { + pixmap = QPixmap( DesktopIcon(QLatin1String( "mail-message" ), KIconLoader::SizeSmall) ); + } else { + pixmap = QPixmap( DesktopIcon(QLatin1String( "document-multiple" ), KIconLoader::SizeSmall) ); + } + + // Calculate hotspot (as in Konqueror) + if( !pixmap.isNull() ) { + drag->setHotSpot( QPoint( pixmap.width() / 2, pixmap.height() / 2 ) ); + drag->setPixmap( pixmap ); + } + + if ( readOnly ) + drag->exec( Qt::CopyAction ); + else + drag->exec( Qt::CopyAction | Qt::MoveAction ); } Item::List Widget::Private::selectionAsItems() const { - Item::List res; - QList selection = q->view()->selectionAsMessageItemList(); + Item::List res; + QList selection = q->view()->selectionAsMessageItemList(); - foreach ( Core::MessageItem *mi, selection ) { - Item i = itemForRow( mi->currentModelIndexRow() ); - Q_ASSERT( i.isValid() ); - res << i; - } + foreach ( Core::MessageItem *mi, selection ) { + Item i = itemForRow( mi->currentModelIndexRow() ); + Q_ASSERT( i.isValid() ); + res << i; + } - return res; + return res; } Item Widget::Private::itemForRow( int row ) const { - return static_cast( q->storageModel() )->itemForRow( row ); + return static_cast( q->storageModel() )->itemForRow( row ); } KMime::Message::Ptr Widget::Private::messageForRow( int row ) const { - return static_cast( q->storageModel() )->messageForRow( row ); + return static_cast( q->storageModel() )->messageForRow( row ); } Item Widget::currentItem() const { - Core::MessageItem *mi = view()->currentMessageItem(); + Core::MessageItem *mi = view()->currentMessageItem(); - if ( mi == 0 ) { - return Item(); - } + if ( mi == 0 ) { + return Item(); + } - return d->itemForRow( mi->currentModelIndexRow() ); + return d->itemForRow( mi->currentModelIndexRow() ); } KMime::Message::Ptr Widget::currentMessage() const { - Core::MessageItem *mi = view()->currentMessageItem(); + Core::MessageItem *mi = view()->currentMessageItem(); - if ( mi == 0 ) { - return KMime::Message::Ptr(); - } + if ( mi == 0 ) { + return KMime::Message::Ptr(); + } - return d->messageForRow( mi->currentModelIndexRow() ); + return d->messageForRow( mi->currentModelIndexRow() ); } QList Widget::selectionAsMessageList( bool includeCollapsedChildren ) const { - QList lstMiPtr; - QList lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren ); - if ( lstMi.isEmpty() ) { - return lstMiPtr; - } - foreach( Core::MessageItem *it, lstMi ) { - lstMiPtr.append( d->messageForRow( it->currentModelIndexRow() ) ); - } - return lstMiPtr; + QList lstMiPtr; + QList lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren ); + if ( lstMi.isEmpty() ) { + return lstMiPtr; + } + foreach( Core::MessageItem *it, lstMi ) { + lstMiPtr.append( d->messageForRow( it->currentModelIndexRow() ) ); + } + return lstMiPtr; } QList Widget::selectionAsMessageItemList( bool includeCollapsedChildren ) const { - QList lstMiPtr; - QList lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren ); - if ( lstMi.isEmpty() ) { - return lstMiPtr; - } - foreach( Core::MessageItem *it, lstMi ) { - lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ) ); - } - return lstMiPtr; + QList lstMiPtr; + QList lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren ); + if ( lstMi.isEmpty() ) { + return lstMiPtr; + } + foreach( Core::MessageItem *it, lstMi ) { + lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ) ); + } + return lstMiPtr; } QVector Widget::selectionAsMessageItemListId( bool includeCollapsedChildren ) const { - QVector lstMiPtr; - QList lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren ); - if ( lstMi.isEmpty() ) { - return lstMiPtr; - } - foreach( Core::MessageItem *it, lstMi ) { - lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ).id() ); - } - return lstMiPtr; + QVector lstMiPtr; + QList lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren ); + if ( lstMi.isEmpty() ) { + return lstMiPtr; + } + foreach( Core::MessageItem *it, lstMi ) { + lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ).id() ); + } + return lstMiPtr; } QList Widget::selectionAsListMessageId( bool includeCollapsedChildren ) const { - QList lstMiPtr; - QList lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren ); - if ( lstMi.isEmpty() ) { - return lstMiPtr; - } - foreach( Core::MessageItem *it, lstMi ) { - lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ).id() ); - } - return lstMiPtr; + QList lstMiPtr; + QList lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren ); + if ( lstMi.isEmpty() ) { + return lstMiPtr; + } + foreach( Core::MessageItem *it, lstMi ) { + lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ).id() ); + } + return lstMiPtr; } QList Widget::currentThreadAsMessageList() const { - QList lstMiPtr; - QList lstMi = view()->currentThreadAsMessageItemList(); - if ( lstMi.isEmpty() ) { + QList lstMiPtr; + QList lstMi = view()->currentThreadAsMessageItemList(); + if ( lstMi.isEmpty() ) { + return lstMiPtr; + } + foreach( Core::MessageItem *it, lstMi ) { + lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ) ); + } return lstMiPtr; - } - foreach( Core::MessageItem *it, lstMi ) { - lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ) ); - } - return lstMiPtr; } QList Widget::currentFilterStatus() const { - return view()->currentFilterStatus(); + return view()->currentFilterStatus(); } QString Widget::currentFilterSearchString() const { - return view()->currentFilterSearchString(); + return view()->currentFilterSearchString(); } bool Widget::isThreaded() const { - return view()->isThreaded(); + return view()->isThreaded(); } bool Widget::selectionEmpty() const { - return view()->selectionEmpty(); + return view()->selectionEmpty(); } bool Widget::getSelectionStats( - Akonadi::Item::List &selectedItems, - Akonadi::Item::List &selectedVisibleItems, - bool * allSelectedBelongToSameThread, - bool includeCollapsedChildren ) const -{ - if ( !storageModel() ) - return false; - - selectedItems.clear(); - selectedVisibleItems.clear(); - - QList< Core::MessageItem * > selected = view()->selectionAsMessageItemList( includeCollapsedChildren ); - - Core::MessageItem * topmost = 0; - - *allSelectedBelongToSameThread = true; - - foreach( Core::MessageItem *it, selected ) { - const Item item = d->itemForRow( it->currentModelIndexRow() ); - selectedItems.append( item ); - if ( view()->isDisplayedWithParentsExpanded( it ) ) - selectedVisibleItems.append( item ); - if ( topmost == 0 ) - topmost = ( *it ).topmostMessage(); - else { - if ( topmost != ( *it ).topmostMessage() ) - *allSelectedBelongToSameThread = false; + Akonadi::Item::List &selectedItems, + Akonadi::Item::List &selectedVisibleItems, + bool * allSelectedBelongToSameThread, + bool includeCollapsedChildren ) const +{ + if ( !storageModel() ) + return false; + + selectedItems.clear(); + selectedVisibleItems.clear(); + + QList< Core::MessageItem * > selected = view()->selectionAsMessageItemList( includeCollapsedChildren ); + + Core::MessageItem * topmost = 0; + + *allSelectedBelongToSameThread = true; + + foreach( Core::MessageItem *it, selected ) { + const Item item = d->itemForRow( it->currentModelIndexRow() ); + selectedItems.append( item ); + if ( view()->isDisplayedWithParentsExpanded( it ) ) + selectedVisibleItems.append( item ); + if ( topmost == 0 ) + topmost = ( *it ).topmostMessage(); + else { + if ( topmost != ( *it ).topmostMessage() ) + *allSelectedBelongToSameThread = false; + } } - } - return true; + return true; } void Widget::deletePersistentSet( MessageList::Core::MessageItemSetReference ref ) { - view()->deletePersistentSet( ref ); + view()->deletePersistentSet( ref ); } void Widget::markMessageItemsAsAboutToBeRemoved( MessageList::Core::MessageItemSetReference ref, bool bMark ) { - QList< Core::MessageItem * > lstPersistent = view()->persistentSetCurrentMessageItemList( ref ); - if ( !lstPersistent.isEmpty() ) - view()->markMessageItemsAsAboutToBeRemoved( lstPersistent, bMark ); + QList< Core::MessageItem * > lstPersistent = view()->persistentSetCurrentMessageItemList( ref ); + if ( !lstPersistent.isEmpty() ) + view()->markMessageItemsAsAboutToBeRemoved( lstPersistent, bMark ); } QList Widget::itemListFromPersistentSet( MessageList::Core::MessageItemSetReference ref ) { - QList lstItem; - QList< Core::MessageItem * > refList = view()->persistentSetCurrentMessageItemList( ref ); - if ( !refList.isEmpty() ) { - foreach( Core::MessageItem *it, refList ) { - lstItem.append( d->itemForRow( it->currentModelIndexRow() ) ); + QList lstItem; + QList< Core::MessageItem * > refList = view()->persistentSetCurrentMessageItemList( ref ); + if ( !refList.isEmpty() ) { + foreach( Core::MessageItem *it, refList ) { + lstItem.append( d->itemForRow( it->currentModelIndexRow() ) ); + } } - } - return lstItem; + return lstItem; } MessageList::Core::MessageItemSetReference Widget::selectionAsPersistentSet( bool includeCollapsedChildren ) const { - QList lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren ); - if ( lstMi.isEmpty() ) { - return -1; - } - return view()->createPersistentSet( lstMi ); + QList lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren ); + if ( lstMi.isEmpty() ) { + return -1; + } + return view()->createPersistentSet( lstMi ); } MessageList::Core::MessageItemSetReference Widget::currentThreadAsPersistentSet() const { - QList lstMi = view()->currentThreadAsMessageItemList(); - if ( lstMi.isEmpty() ) { - return -1; - } - return view()->createPersistentSet( lstMi ); + QList lstMi = view()->currentThreadAsMessageItemList(); + if ( lstMi.isEmpty() ) { + return -1; + } + return view()->createPersistentSet( lstMi ); } Akonadi::Collection Widget::currentCollection() const { - Collection::List collections = static_cast( storageModel() )->displayedCollections(); - if ( collections.size()!=1 ) - return Akonadi::Collection(); // no folder here or too many (in case we can't decide where the drop will end) - return collections.first(); + Collection::List collections = static_cast( storageModel() )->displayedCollections(); + if ( collections.size()!=1 ) + return Akonadi::Collection(); // no folder here or too many (in case we can't decide where the drop will end) + return collections.first(); } void Widget::slotCollapseItem() { - view()->setCollapseItem(d->mGroupHeaderItemIndex); + view()->setCollapseItem(d->mGroupHeaderItemIndex); } void Widget::slotExpandItem() { - view()->setExpandItem(d->mGroupHeaderItemIndex); + view()->setExpandItem(d->mGroupHeaderItemIndex); } diff -Nru kdepim-4.12.97/messagelist/widget.h kdepim-4.13.0/messagelist/widget.h --- kdepim-4.12.97/messagelist/widget.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messagelist/widget.h 2014-04-10 07:40:20.000000000 +0000 @@ -44,16 +44,16 @@ */ class MESSAGELIST_EXPORT Widget : public MessageList::Core::Widget { - Q_OBJECT + Q_OBJECT public: - /** + /** * Create a new message list widget. */ - explicit Widget( QWidget *parent ); - ~Widget(); + explicit Widget( QWidget *parent ); + ~Widget(); - /** + /** * Sets the XML GUI client which the view is used in. * * This is needed if you want to use the built-in context menu. @@ -61,27 +61,27 @@ * * @param xmlGuiClient The KXMLGUIClient the view is used in. */ - void setXmlGuiClient( KXMLGUIClient *xmlGuiClient ); + void setXmlGuiClient( KXMLGUIClient *xmlGuiClient ); - /** + /** * Returns the current message for the list as Akonadi::Item. * May return an invalid Item if there is no current message or no current folder. */ - Akonadi::Item currentItem() const; + Akonadi::Item currentItem() const; - /** + /** * Returns the current message for the list as KMime::Message::Ptr. * May return 0 if there is no current message or no current folder. */ - KMime::Message::Ptr currentMessage() const; + KMime::Message::Ptr currentMessage() const; - /** + /** * Returns true if this drag can be accepted by the underlying view */ - bool canAcceptDrag( const QDropEvent *e ); + bool canAcceptDrag( const QDropEvent *e ); - /** + /** * Selects the next message item in the view. * * messageTypeFilter can be used to restrict the selection to only certain message types. @@ -94,12 +94,12 @@ * If loop is true then the "next" algorithm will restart from the beginning * of the list if the end is reached, otherwise it will just stop returning false. */ - bool selectNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, - MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, - bool centerItem, - bool loop ); + bool selectNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, + MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, + bool centerItem, + bool loop ); - /** + /** * Selects the previous message item in the view. * If centerItem is true then the specified item will be positioned * at the center of the view, if possible. @@ -112,12 +112,12 @@ * If loop is true then the "previous" algorithm will restart from the end * of the list if the beginning is reached, otherwise it will just stop returning false. */ - bool selectPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, - MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, - bool centerItem, - bool loop ); + bool selectPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, + MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, + bool centerItem, + bool loop ); - /** + /** * Focuses the next message item in the view without actually selecting it. * * messageTypeFilter can be used to restrict the selection to only certain message types. @@ -127,9 +127,9 @@ * If loop is true then the "next" algorithm will restart from the beginning * of the list if the end is reached, otherwise it will just stop returning false. */ - bool focusNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); + bool focusNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); - /** + /** * Focuses the previous message item in the view without actually selecting it. * * messageTypeFilter can be used to restrict the selection to only certain message types. @@ -139,17 +139,17 @@ * If loop is true then the "previous" algorithm will restart from the end * of the list if the beginning is reached, otherwise it will just stop returning false. */ - bool focusPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); + bool focusPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop ); - /** + /** * Selects the currently focused message item. May do nothing if the * focused message item is already selected (which is very likely). * If centerItem is true then the specified item will be positioned * at the center of the view, if possible. */ - void selectFocusedMessageItem( bool centerItem ); + void selectFocusedMessageItem( bool centerItem ); - /** + /** * Selects the first message item in the view that matches the specified Core::MessageTypeFilter. * If centerItem is true then the specified item will be positioned * at the center of the view, if possible. @@ -164,47 +164,47 @@ * * The function returns true if a message was selected and false otherwise. */ - bool selectFirstMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem ); + bool selectFirstMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem ); - /** + /** * Selects the last message item in the view that matches the specified Core::MessageTypeFilter. * If centerItem is true then the specified item will be positioned * at the center of the view, if possible. * * The function returns true if a message was selected and false otherwise. */ - bool selectLastMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem ); + bool selectLastMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem ); - /** + /** * Selects all the items in the current folder. */ - void selectAll(); - /** + void selectAll(); + /** * If expand is true then it expands the current thread, otherwise * collapses it. */ - void setCurrentThreadExpanded( bool expand ); + void setCurrentThreadExpanded( bool expand ); - /** + /** * If expand is true then it expands all the threads, otherwise * collapses them. */ - void setAllThreadsExpanded( bool expand ); + void setAllThreadsExpanded( bool expand ); - /** + /** * If expand is true then it expands all the groups (only the toplevel * group item: inner threads are NOT expanded). If expand is false * then it collapses all the groups. If no grouping is in effect * then this function does nothing. */ - void setAllGroupsExpanded( bool expand ); + void setAllGroupsExpanded( bool expand ); - /** + /** * Sets the focus on the quick search line of the currently active tab. */ - void focusQuickSearch(); + void focusQuickSearch(); - /** + /** * Returns the currently selected KMime::Message::Ptr (bound to current StorageModel). * The list may be empty if there are no selected messages or no StorageModel. * @@ -215,9 +215,9 @@ * to the main even loop. Don't store it for any longer. If you need to reference * this set of messages at a later stage then take a look at createPersistentSet(). */ - QList selectionAsMessageList( bool includeCollapsedChildren = true ) const; + QList selectionAsMessageList( bool includeCollapsedChildren = true ) const; - /** + /** * Returns the currently selected Items (bound to current StorageModel). * The list may be empty if there are no selected messages or no StorageModel. * @@ -228,9 +228,9 @@ * to the main even loop. Don't store it for any longer. If you need to reference * this set of messages at a later stage then take a look at createPersistentSet(). */ - QList selectionAsMessageItemList( bool includeCollapsedChildren = true ) const; + QList selectionAsMessageItemList( bool includeCollapsedChildren = true ) const; - /** + /** * Returns the currently selected Items id (bound to current StorageModel). * The list may be empty if there are no selected messages or no StorageModel. * @@ -242,10 +242,10 @@ * this set of messages at a later stage then take a look at createPersistentSet(). */ - QVector selectionAsMessageItemListId( bool includeCollapsedChildren ) const; - QList selectionAsListMessageId( bool includeCollapsedChildren ) const; + QVector selectionAsMessageItemListId( bool includeCollapsedChildren ) const; + QList selectionAsListMessageId( bool includeCollapsedChildren ) const; - /** + /** * Returns the Akonadi::Item bound to the current StorageModel that * are part of the current thread. The current thread is the thread * that contains currentMessageItem(). @@ -255,30 +255,30 @@ * to the main even loop. Don't store it for any longer. If you need to reference * this set of messages at a later stage then take a look at createPersistentSet(). */ - QList currentThreadAsMessageList() const; + QList currentThreadAsMessageList() const; - /** + /** * Returns the Akonadi::MessageStatus in the current quicksearch field. */ - QList currentFilterStatus() const; + QList currentFilterStatus() const; - /** + /** * Returns the search term in the current quicksearch field. */ - QString currentFilterSearchString() const; + QString currentFilterSearchString() const; - /** + /** * Returns true if the current Aggregation is threaded, false otherwise * (or if there is no current Aggregation). */ - bool isThreaded() const; + bool isThreaded() const; - /** + /** * Fast function that determines if the selection is empty */ - bool selectionEmpty() const; + bool selectionEmpty() const; - /** + /** * Fills the lists of the selected message serial numbers and of the selected+visible ones. * Returns true if the returned stats are valid (there is a current folder after all) * and false otherwise. This is called by KMMainWidget in a single place so we optimize by @@ -288,106 +288,106 @@ * collapsed items are also included in the stats */ - bool getSelectionStats( Akonadi::Item::List &selectedSernums, - Akonadi::Item::List &selectedVisibleSernums, - bool * allSelectedBelongToSameThread, - bool includeCollapsedChildren = true ) const; - /** + bool getSelectionStats( Akonadi::Item::List &selectedSernums, + Akonadi::Item::List &selectedVisibleSernums, + bool * allSelectedBelongToSameThread, + bool includeCollapsedChildren = true ) const; + /** * Deletes the persistent set pointed by the specified reference. * If the set does not exist anymore, nothing happens. */ - void deletePersistentSet( MessageList::Core::MessageItemSetReference ref ); + void deletePersistentSet( MessageList::Core::MessageItemSetReference ref ); - /** + /** * If bMark is true this function marks the messages as "about to be removed" * so they appear dimmer and aren't selectable in the view. * If bMark is false then this function clears the "about to be removed" state * for the specified MessageItems. */ - void markMessageItemsAsAboutToBeRemoved( MessageList::Core::MessageItemSetReference ref, bool bMark ); + void markMessageItemsAsAboutToBeRemoved( MessageList::Core::MessageItemSetReference ref, bool bMark ); - /** + /** * Return Akonadi::Item from messageItemReference */ - QList itemListFromPersistentSet( MessageList::Core::MessageItemSetReference ref ); + QList itemListFromPersistentSet( MessageList::Core::MessageItemSetReference ref ); - /** + /** * Return a persistent set from current selection */ - MessageList::Core::MessageItemSetReference selectionAsPersistentSet( bool includeCollapsedChildren = true ) const; + MessageList::Core::MessageItemSetReference selectionAsPersistentSet( bool includeCollapsedChildren = true ) const; - /** + /** * Return a persistent set from current thread */ - MessageList::Core::MessageItemSetReference currentThreadAsPersistentSet() const; - Akonadi::Collection currentCollection() const; + MessageList::Core::MessageItemSetReference currentThreadAsPersistentSet() const; + Akonadi::Collection currentCollection() const; - void setQuickSearchClickMessage(const QString &msg); + void setQuickSearchClickMessage(const QString &msg); protected: - /** + /** * Reimplemented from MessageList::Core::Widget */ - virtual void fillMessageTagCombo(); + virtual void fillMessageTagCombo(); - /** + /** * Reimplemented from MessageList::Core::Widget */ - virtual void viewMessageSelected( MessageList::Core::MessageItem *msg ); + virtual void viewMessageSelected( MessageList::Core::MessageItem *msg ); - /** + /** * Reimplemented from MessageList::Core::Widget */ - virtual void viewMessageActivated( MessageList::Core::MessageItem *msg ); + virtual void viewMessageActivated( MessageList::Core::MessageItem *msg ); - /** + /** * Reimplemented from MessageList::Core::Widget */ - virtual void viewSelectionChanged(); + virtual void viewSelectionChanged(); - /** + /** * Reimplemented from MessageList::Core::Widget */ - virtual void viewMessageListContextPopupRequest( const QList< MessageList::Core::MessageItem * > &selectedItems, const QPoint &globalPos ); + virtual void viewMessageListContextPopupRequest( const QList< MessageList::Core::MessageItem * > &selectedItems, const QPoint &globalPos ); - /** + /** * Reimplemented from MessageList::Core::Widget */ - virtual void viewGroupHeaderContextPopupRequest( MessageList::Core::GroupHeaderItem *group, const QPoint &globalPos ); + virtual void viewGroupHeaderContextPopupRequest( MessageList::Core::GroupHeaderItem *group, const QPoint &globalPos ); - /** + /** * Reimplemented from MessageList::Core::Widget */ - virtual void viewDragEnterEvent( QDragEnterEvent * e ); + virtual void viewDragEnterEvent( QDragEnterEvent * e ); - /** + /** * Reimplemented from MessageList::Core::Widget */ - virtual void viewDragMoveEvent( QDragMoveEvent * e ); + virtual void viewDragMoveEvent( QDragMoveEvent * e ); - /** + /** * Reimplemented from MessageList::Core::Widget */ - virtual void viewDropEvent( QDropEvent * e ); + virtual void viewDropEvent( QDropEvent * e ); - /** + /** * Reimplemented from MessageList::Core::Widget */ - virtual void viewStartDragRequest(); + virtual void viewStartDragRequest(); - /** + /** * Reimplemented from MessageList::Core::Widget */ - virtual void viewMessageStatusChangeRequest( MessageList::Core::MessageItem *msg, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear ); + virtual void viewMessageStatusChangeRequest( MessageList::Core::MessageItem *msg, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear ); private Q_SLOTS: - void slotCollapseItem(); - void slotExpandItem(); - void slotTagsFetched(KJob *job); + void slotCollapseItem(); + void slotExpandItem(); + void slotTagsFetched(KJob *job); signals: - /** + /** * Emitted when a message is selected (that is, single clicked and thus made current in the view) * Note that this message CAN be 0 (when the current item is cleared, for example). * @@ -397,26 +397,26 @@ * this signal only for the last clicked message (or at all, if the last shift+clicked * thing is a group header...). You should handle selection changed in this case. */ - void messageSelected( const Akonadi::Item &item ); + void messageSelected( const Akonadi::Item &item ); - /** + /** * Emitted when a message is doubleclicked or activated by other input means */ - void messageActivated( const Akonadi::Item &item ); + void messageActivated( const Akonadi::Item &item ); - /** + /** * Emitted when the selection in the view changes. */ - void selectionChanged(); + void selectionChanged(); - /** + /** * Emitted when a message wants its status to be changed */ - void messageStatusChangeRequest( const Akonadi::Item &item, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear ); + void messageStatusChangeRequest( const Akonadi::Item &item, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear ); private: - class Private; - Private * const d; + class Private; + Private * const d; }; } // namespace MessageList diff -Nru kdepim-4.12.97/messageviewer/a11y/accessiblemailwebview.cpp kdepim-4.13.0/messageviewer/a11y/accessiblemailwebview.cpp --- kdepim-4.12.97/messageviewer/a11y/accessiblemailwebview.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/a11y/accessiblemailwebview.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -21,112 +21,112 @@ #include QString Q_GUI_EXPORT qTextAfterOffsetFromString( int offset, QAccessible2::BoundaryType boundaryType, - int *startOffset, int *endOffset, const QString& text ); + int *startOffset, int *endOffset, const QString& text ); QString Q_GUI_EXPORT qTextBeforeOffsetFromString( int offset, QAccessible2::BoundaryType boundaryType, - int *startOffset, int *endOffset, const QString& text ); + int *startOffset, int *endOffset, const QString& text ); QString Q_GUI_EXPORT qTextAtOffsetFromString( int offset, QAccessible2::BoundaryType boundaryType, - int *startOffset, int *endOffset, const QString& text ); + int *startOffset, int *endOffset, const QString& text ); AccessibleMailWebView::AccessibleMailWebView( MessageViewer::MailWebView* widget ): - QAccessibleWidgetEx( widget, QAccessible::Document ) + QAccessibleWidgetEx( widget, QAccessible::Document ) { - m_widget = widget; + m_widget = widget; } int AccessibleMailWebView::characterCount() { - return m_widget->page()->mainFrame()->toPlainText().size(); + return m_widget->page()->mainFrame()->toPlainText().size(); } int AccessibleMailWebView::selectionCount() { - return m_widget->hasSelection() ? 1 : 0; + return m_widget->hasSelection() ? 1 : 0; } void AccessibleMailWebView::addSelection( int startOffset, int endOffset ) { - Q_UNUSED( startOffset ); - Q_UNUSED( endOffset ); + Q_UNUSED( startOffset ); + Q_UNUSED( endOffset ); } void AccessibleMailWebView::removeSelection( int selectionIndex ) { - if ( selectionIndex == 0 ) - m_widget->clearSelection(); + if ( selectionIndex == 0 ) + m_widget->clearSelection(); } void AccessibleMailWebView::setSelection( int selectionIndex, int startOffset, int endOffset ) { - Q_UNUSED( selectionIndex ); - Q_UNUSED( startOffset ); - Q_UNUSED( endOffset ); + Q_UNUSED( selectionIndex ); + Q_UNUSED( startOffset ); + Q_UNUSED( endOffset ); } void AccessibleMailWebView::setCursorPosition( int position ) { - Q_UNUSED( position ); + Q_UNUSED( position ); } QString AccessibleMailWebView::text( int startOffset, int endOffset ) { - QString text = m_widget->page()->mainFrame()->toPlainText(); - text.truncate( endOffset ); - text.remove( 0, startOffset ); - return text; + QString text = m_widget->page()->mainFrame()->toPlainText(); + text.truncate( endOffset ); + text.remove( 0, startOffset ); + return text; } QString AccessibleMailWebView::attributes( int offset, int* startOffset, int* endOffset ) { - Q_UNUSED( offset ); - Q_UNUSED( startOffset ); - Q_UNUSED( endOffset ); - return QString(); + Q_UNUSED( offset ); + Q_UNUSED( startOffset ); + Q_UNUSED( endOffset ); + return QString(); } void AccessibleMailWebView::selection( int selectionIndex, int* startOffset, int* endOffset ) { - Q_UNUSED( selectionIndex ); - *startOffset = -1; - *endOffset = -1; + Q_UNUSED( selectionIndex ); + *startOffset = -1; + *endOffset = -1; } QRect AccessibleMailWebView::characterRect( int offset, QAccessible2::CoordinateType coordType ) { - Q_UNUSED( offset ); - Q_UNUSED( coordType ); - return QRect(); + Q_UNUSED( offset ); + Q_UNUSED( coordType ); + return QRect(); } int AccessibleMailWebView::offsetAtPoint( const QPoint& point, QAccessible2::CoordinateType coordType ) { - Q_UNUSED( point ); - Q_UNUSED( coordType ); - return 0; + Q_UNUSED( point ); + Q_UNUSED( coordType ); + return 0; } int AccessibleMailWebView::cursorPosition() { - return 0; + return 0; } void AccessibleMailWebView::scrollToSubstring( int startIndex, int endIndex ) { - Q_UNUSED( startIndex ); - Q_UNUSED( endIndex ); + Q_UNUSED( startIndex ); + Q_UNUSED( endIndex ); } QString AccessibleMailWebView::textAfterOffset( int offset, QAccessible2::BoundaryType boundaryType, int* startOffset, int* endOffset ) { - return qTextAfterOffsetFromString( offset, boundaryType, startOffset, endOffset, m_widget->page()->mainFrame()->toPlainText() ); + return qTextAfterOffsetFromString( offset, boundaryType, startOffset, endOffset, m_widget->page()->mainFrame()->toPlainText() ); } QString AccessibleMailWebView::textBeforeOffset( int offset, QAccessible2::BoundaryType boundaryType, int* startOffset, int* endOffset ) { - return qTextBeforeOffsetFromString( offset, boundaryType, startOffset, endOffset, m_widget->page()->mainFrame()->toPlainText() ); + return qTextBeforeOffsetFromString( offset, boundaryType, startOffset, endOffset, m_widget->page()->mainFrame()->toPlainText() ); } QString AccessibleMailWebView::textAtOffset( int offset, QAccessible2::BoundaryType boundaryType, int* startOffset, int* endOffset ) { - return qTextAtOffsetFromString( offset, boundaryType, startOffset, endOffset, m_widget->page()->mainFrame()->toPlainText() ); + return qTextAtOffsetFromString( offset, boundaryType, startOffset, endOffset, m_widget->page()->mainFrame()->toPlainText() ); } diff -Nru kdepim-4.12.97/messageviewer/a11y/accessiblemailwebview.h kdepim-4.13.0/messageviewer/a11y/accessiblemailwebview.h --- kdepim-4.12.97/messageviewer/a11y/accessiblemailwebview.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/a11y/accessiblemailwebview.h 2014-04-10 07:40:20.000000000 +0000 @@ -3,7 +3,7 @@ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either + License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, @@ -11,7 +11,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public + You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ @@ -22,41 +22,41 @@ #include namespace MessageViewer { - class MailWebView; +class MailWebView; } class AccessibleMailWebView: public QAccessibleWidgetEx, - public QAccessibleTextInterface + public QAccessibleTextInterface { - Q_ACCESSIBLE_OBJECT + Q_ACCESSIBLE_OBJECT public: - explicit AccessibleMailWebView( MessageViewer::MailWebView *widget ); + explicit AccessibleMailWebView( MessageViewer::MailWebView *widget ); - virtual int characterCount(); + virtual int characterCount(); - virtual int selectionCount(); - virtual void addSelection( int startOffset, int endOffset ); - virtual void removeSelection( int selectionIndex ); - virtual void setSelection( int selectionIndex, int startOffset, int endOffset ); - virtual void setCursorPosition( int ); - - // unhide overload QString text(Text, int) from QAccessible - using QAccessibleWidgetEx::text; - - virtual QString text( int startOffset, int endOffset ); - - virtual QString attributes( int offset, int* startOffset, int* endOffset ); - - virtual void selection( int selectionIndex, int* startOffset, int* endOffset ); - virtual QRect characterRect( int offset, QAccessible2::CoordinateType coordType ); - virtual int offsetAtPoint( const QPoint& point, QAccessible2::CoordinateType coordType ); - virtual int cursorPosition(); - virtual void scrollToSubstring( int startIndex, int endIndex ); - virtual QString textAfterOffset( int offset, QAccessible2::BoundaryType boundaryType, int* startOffset, int* endOffset ); - virtual QString textBeforeOffset( int offset, QAccessible2::BoundaryType boundaryType, int* startOffset, int* endOffset ); - virtual QString textAtOffset( int offset, QAccessible2::BoundaryType boundaryType, int* startOffset, int* endOffset ); + virtual int selectionCount(); + virtual void addSelection( int startOffset, int endOffset ); + virtual void removeSelection( int selectionIndex ); + virtual void setSelection( int selectionIndex, int startOffset, int endOffset ); + virtual void setCursorPosition( int ); + + // unhide overload QString text(Text, int) from QAccessible + using QAccessibleWidgetEx::text; + + virtual QString text( int startOffset, int endOffset ); + + virtual QString attributes( int offset, int* startOffset, int* endOffset ); + + virtual void selection( int selectionIndex, int* startOffset, int* endOffset ); + virtual QRect characterRect( int offset, QAccessible2::CoordinateType coordType ); + virtual int offsetAtPoint( const QPoint& point, QAccessible2::CoordinateType coordType ); + virtual int cursorPosition(); + virtual void scrollToSubstring( int startIndex, int endIndex ); + virtual QString textAfterOffset( int offset, QAccessible2::BoundaryType boundaryType, int* startOffset, int* endOffset ); + virtual QString textBeforeOffset( int offset, QAccessible2::BoundaryType boundaryType, int* startOffset, int* endOffset ); + virtual QString textAtOffset( int offset, QAccessible2::BoundaryType boundaryType, int* startOffset, int* endOffset ); private: - MessageViewer::MailWebView *m_widget; + MessageViewer::MailWebView *m_widget; }; #endif diff -Nru kdepim-4.12.97/messageviewer/a11y/messagevieweraccessiblewidgetfactory.cpp kdepim-4.13.0/messageviewer/a11y/messagevieweraccessiblewidgetfactory.cpp --- kdepim-4.12.97/messageviewer/a11y/messagevieweraccessiblewidgetfactory.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/a11y/messagevieweraccessiblewidgetfactory.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -24,20 +24,20 @@ QAccessibleInterface *MessageViewerAccessibleWidgetFactory::create( const QString &key, QObject *object ) { - if ( key == QLatin1String( "MessageViewer::MailWebView" ) ) { - return new AccessibleMailWebView( reinterpret_cast< MessageViewer::MailWebView* >( object ) ); - } - return 0; + if ( key == QLatin1String( "MessageViewer::MailWebView" ) ) { + return new AccessibleMailWebView( reinterpret_cast< MessageViewer::MailWebView* >( object ) ); + } + return 0; } MessageViewerAccessibleWidgetFactory::MessageViewerAccessibleWidgetFactory( QObject *parent ): - QAccessiblePlugin( parent ) + QAccessiblePlugin( parent ) { } QStringList MessageViewerAccessibleWidgetFactory::keys() const { - QStringList l; - l.append( QLatin1String( "MessageViewer::MailWebView" ) ); - return l; + QStringList l; + l.append( QLatin1String( "MessageViewer::MailWebView" ) ); + return l; } diff -Nru kdepim-4.12.97/messageviewer/a11y/messagevieweraccessiblewidgetfactory.h kdepim-4.13.0/messageviewer/a11y/messagevieweraccessiblewidgetfactory.h --- kdepim-4.12.97/messageviewer/a11y/messagevieweraccessiblewidgetfactory.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/a11y/messagevieweraccessiblewidgetfactory.h 2014-04-10 07:40:20.000000000 +0000 @@ -23,9 +23,9 @@ class MessageViewerAccessibleWidgetFactory: public QAccessiblePlugin { public: - explicit MessageViewerAccessibleWidgetFactory( QObject *parent = 0 ); - virtual QAccessibleInterface *create( const QString &key, QObject *object ); - virtual QStringList keys() const; + explicit MessageViewerAccessibleWidgetFactory( QObject *parent = 0 ); + virtual QAccessibleInterface *create( const QString &key, QObject *object ); + virtual QStringList keys() const; }; #endif diff -Nru kdepim-4.12.97/messageviewer/header/customheadersettingwidget.cpp kdepim-4.13.0/messageviewer/header/customheadersettingwidget.cpp --- kdepim-4.12.97/messageviewer/header/customheadersettingwidget.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/header/customheadersettingwidget.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -44,6 +44,8 @@ mHeaders = new PimCommon::SimpleStringListEditor( this, PimCommon::SimpleStringListEditor::All, i18n("A&dd..."), i18n("Remo&ve"), i18n("&Modify..."), i18n("Header:") ); + mHeaders->setUpDownAutoRepeat(true); + connect(mHeaders, SIGNAL(changed()), this, SIGNAL(changed())); topLayout->addWidget(mHeaders); diff -Nru kdepim-4.12.97/messageviewer/header/grantleeheaderformatter.cpp kdepim-4.13.0/messageviewer/header/grantleeheaderformatter.cpp --- kdepim-4.12.97/messageviewer/header/grantleeheaderformatter.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/header/grantleeheaderformatter.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -71,10 +71,11 @@ { d->templateLoader->setTemplateDirs( QStringList() << absolutPath ); Grantlee::Template headerTemplate = d->engine->loadByName( filename ); + qDebug()<<" absolutPath"<error() ) { return headerTemplate->errorString(); } - return format(headerTemplate, displayExtraHeaders, isPrinting, style, message); + return format(absolutPath, headerTemplate, displayExtraHeaders, isPrinting, style, message); } QString GrantleeHeaderFormatter::toHtml(const GrantleeTheme::Theme &theme, bool isPrinting, const MessageViewer::HeaderStyle *style, KMime::Message *message) const @@ -90,10 +91,10 @@ errorMessage = headerTemplate->errorString(); return errorMessage; } - return format(headerTemplate, theme.displayExtraVariables(), isPrinting, style, message); + return format(theme.absolutePath(), headerTemplate, theme.displayExtraVariables(), isPrinting, style, message); } -QString GrantleeHeaderFormatter::format(Grantlee::Template headerTemplate, const QStringList &displayExtraHeaders, bool isPrinting, const MessageViewer::HeaderStyle *style, KMime::Message *message) const +QString GrantleeHeaderFormatter::format(const QString &absolutePath, Grantlee::Template headerTemplate, const QStringList &displayExtraHeaders, bool isPrinting, const MessageViewer::HeaderStyle *style, KMime::Message *message) const { QVariantHash headerObject; @@ -102,7 +103,8 @@ // the "Re:" and "Fwd:" prefixes would always cause the subject to be // considered left-to-right, they are ignored when determining its // direction. - + const QString absoluteThemePath = QLatin1String("file://") + absolutePath + QLatin1Char('/'); + headerObject.insert(QLatin1String("absoluteThemePath"), absoluteThemePath); headerObject.insert(QLatin1String("applicationDir"), QApplication::isRightToLeft() ? QLatin1String("rtl") : QLatin1String("ltr")); headerObject.insert(QLatin1String("subjectDir"), MessageViewer::HeaderStyleUtil::subjectDirectionString( message )); diff -Nru kdepim-4.12.97/messageviewer/header/grantleeheaderformatter.h kdepim-4.13.0/messageviewer/header/grantleeheaderformatter.h --- kdepim-4.12.97/messageviewer/header/grantleeheaderformatter.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/header/grantleeheaderformatter.h 2014-04-10 07:40:20.000000000 +0000 @@ -40,7 +40,7 @@ QString toHtml(const QStringList &displayExtraHeaders, const QString &absolutPath, const QString &filename, const MessageViewer::HeaderStyle *style, KMime::Message *message, bool isPrinting) const; private: - QString format(Grantlee::Template headerTemplate, const QStringList &displayExtraHeaders, bool isPrinting, const MessageViewer::HeaderStyle *style, KMime::Message *message) const; + QString format(const QString &absolutePath, Grantlee::Template headerTemplate, const QStringList &displayExtraHeaders, bool isPrinting, const MessageViewer::HeaderStyle *style, KMime::Message *message) const; class Private; Private *const d; }; diff -Nru kdepim-4.12.97/messageviewer/htmlwriter/filehtmlwriter.cpp kdepim-4.13.0/messageviewer/htmlwriter/filehtmlwriter.cpp --- kdepim-4.12.97/messageviewer/htmlwriter/filehtmlwriter.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/htmlwriter/filehtmlwriter.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -40,72 +40,72 @@ namespace MessageViewer { - FileHtmlWriter::FileHtmlWriter( const QString & filename ) +FileHtmlWriter::FileHtmlWriter( const QString & filename ) : HtmlWriter(), mFile( filename.isEmpty() ? QLatin1String( "filehtmlwriter.out" ) : filename ) - { +{ mStream.setCodec( "UTF-8" ); - } +} - FileHtmlWriter::~FileHtmlWriter() { +FileHtmlWriter::~FileHtmlWriter() { if ( mFile.isOpen() ) { - kWarning() << "FileHtmlWriter: file still open!"; - mStream.setDevice(0); - mFile.close(); + kWarning() << "FileHtmlWriter: file still open!"; + mStream.setDevice(0); + mFile.close(); } - } +} - void FileHtmlWriter::begin( const QString & css ) { +void FileHtmlWriter::begin( const QString & css ) { openOrWarn(); if ( !css.isEmpty() ) - write( QLatin1String("\n") ); - } + write( QLatin1String("\n") ); +} - void FileHtmlWriter::end() { +void FileHtmlWriter::end() { flush(); mStream.setDevice(0); mFile.close(); - } +} - void FileHtmlWriter::reset() { +void FileHtmlWriter::reset() { if ( mFile.isOpen() ) { - mStream.setDevice( 0 ); - mFile.close(); + mStream.setDevice( 0 ); + mFile.close(); } - } +} - void FileHtmlWriter::write( const QString & str ) { +void FileHtmlWriter::write( const QString & str ) { mStream << str.toUtf8(); flush(); - } +} - void FileHtmlWriter::queue( const QString & str ) { +void FileHtmlWriter::queue( const QString & str ) { write( str ); - } +} - void FileHtmlWriter::flush() { +void FileHtmlWriter::flush() { mStream.flush(); mFile.flush(); - } +} - void FileHtmlWriter::openOrWarn() { +void FileHtmlWriter::openOrWarn() { if ( mFile.isOpen() ) { - kWarning() << "FileHtmlWriter: file still open!"; - mStream.setDevice( 0 ); - mFile.close(); + kWarning() << "FileHtmlWriter: file still open!"; + mStream.setDevice( 0 ); + mFile.close(); } if ( !mFile.open( QIODevice::WriteOnly ) ) - kWarning() << "FileHtmlWriter: Cannot open file" << mFile.fileName(); + kWarning() << "FileHtmlWriter: Cannot open file" << mFile.fileName(); else - mStream.setDevice( &mFile ); - } + mStream.setDevice( &mFile ); +} - void FileHtmlWriter::embedPart( const QByteArray & contentId, const QString & url ) { +void FileHtmlWriter::embedPart( const QByteArray & contentId, const QString & url ) { mStream << "" << endl; flush(); - } - void FileHtmlWriter::extraHead( const QString& ) { +} +void FileHtmlWriter::extraHead( const QString& ) { - } +} } // diff -Nru kdepim-4.12.97/messageviewer/htmlwriter/filehtmlwriter.h kdepim-4.13.0/messageviewer/htmlwriter/filehtmlwriter.h --- kdepim-4.12.97/messageviewer/htmlwriter/filehtmlwriter.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/htmlwriter/filehtmlwriter.h 2014-04-10 07:40:20.000000000 +0000 @@ -42,8 +42,8 @@ namespace MessageViewer { - class MESSAGEVIEWER_EXPORT FileHtmlWriter : public HtmlWriter { - public: +class MESSAGEVIEWER_EXPORT FileHtmlWriter : public HtmlWriter { +public: explicit FileHtmlWriter( const QString & filename ); virtual ~FileHtmlWriter(); @@ -55,13 +55,13 @@ void flush(); void embedPart( const QByteArray & contentId, const QString & url ); void extraHead( const QString& str ); - private: +private: void openOrWarn(); - private: +private: QFile mFile; QTextStream mStream; - }; +}; } // namespace MessageViewer diff -Nru kdepim-4.12.97/messageviewer/htmlwriter/teehtmlwriter.cpp kdepim-4.13.0/messageviewer/htmlwriter/teehtmlwriter.cpp --- kdepim-4.12.97/messageviewer/htmlwriter/teehtmlwriter.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/htmlwriter/teehtmlwriter.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -40,58 +40,58 @@ namespace MessageViewer { - TeeHtmlWriter::TeeHtmlWriter( HtmlWriter * writer1, HtmlWriter * writer2 ) +TeeHtmlWriter::TeeHtmlWriter( HtmlWriter * writer1, HtmlWriter * writer2 ) : HtmlWriter() - { +{ if ( writer1 ) - mWriters.append( writer1 ); + mWriters.append( writer1 ); if ( writer2 ) - mWriters.append( writer2 ); - } + mWriters.append( writer2 ); +} - TeeHtmlWriter::~TeeHtmlWriter() { +TeeHtmlWriter::~TeeHtmlWriter() { for ( QList::Iterator it = mWriters.begin(); it != mWriters.end(); ++it ) - delete (*it); - } + delete (*it); +} - void TeeHtmlWriter::addHtmlWriter( HtmlWriter * writer ) { +void TeeHtmlWriter::addHtmlWriter( HtmlWriter * writer ) { if ( writer ) - mWriters.append( writer ); - } + mWriters.append( writer ); +} - void TeeHtmlWriter::begin( const QString & css ) { +void TeeHtmlWriter::begin( const QString & css ) { for ( QList::Iterator it = mWriters.begin(); it != mWriters.end(); ++it ) - (*it)->begin( css ); - } + (*it)->begin( css ); +} - void TeeHtmlWriter::end() { +void TeeHtmlWriter::end() { for ( QList::Iterator it = mWriters.begin(); it != mWriters.end(); ++it ) - (*it)->end(); - } + (*it)->end(); +} - void TeeHtmlWriter::reset() { +void TeeHtmlWriter::reset() { for ( QList::Iterator it = mWriters.begin(); it != mWriters.end(); ++it ) - (*it)->reset(); - } + (*it)->reset(); +} - void TeeHtmlWriter::write( const QString & str ) { +void TeeHtmlWriter::write( const QString & str ) { for ( QList::Iterator it = mWriters.begin(); it != mWriters.end(); ++it ) - (*it)->write( str ); - } + (*it)->write( str ); +} - void TeeHtmlWriter::queue( const QString & str ) { - for ( QList::Iterator it = mWriters.begin(); it != mWriters.end(); ++it ) - (*it)->queue( str ); - } +void TeeHtmlWriter::queue( const QString & str ) { + for ( QList::Iterator it = mWriters.begin(); it != mWriters.end(); ++it ) + (*it)->queue( str ); +} - void TeeHtmlWriter::flush() { +void TeeHtmlWriter::flush() { for ( QList::Iterator it = mWriters.begin(); it != mWriters.end(); ++it ) - (*it)->flush(); - } + (*it)->flush(); +} - void TeeHtmlWriter::embedPart( const QByteArray & contentId, const QString & url ) { +void TeeHtmlWriter::embedPart( const QByteArray & contentId, const QString & url ) { for ( QList::Iterator it = mWriters.begin(); it != mWriters.end(); ++it ) - (*it)->embedPart( contentId, url ); - } - void TeeHtmlWriter::extraHead( const QString& ) {} + (*it)->embedPart( contentId, url ); +} +void TeeHtmlWriter::extraHead( const QString& ) {} } // diff -Nru kdepim-4.12.97/messageviewer/htmlwriter/teehtmlwriter.h kdepim-4.13.0/messageviewer/htmlwriter/teehtmlwriter.h --- kdepim-4.12.97/messageviewer/htmlwriter/teehtmlwriter.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/htmlwriter/teehtmlwriter.h 2014-04-10 07:40:20.000000000 +0000 @@ -40,11 +40,11 @@ namespace MessageViewer { - /** @short A HtmlWriter that dispatches all calls to a list of other HtmlWriters +/** @short A HtmlWriter that dispatches all calls to a list of other HtmlWriters @author Marc Mutz **/ - class TeeHtmlWriter : public HtmlWriter { - public: +class TeeHtmlWriter : public HtmlWriter { +public: explicit TeeHtmlWriter( HtmlWriter * writer1 = 0, HtmlWriter * writer2 = 0 ); virtual ~TeeHtmlWriter(); @@ -61,12 +61,12 @@ void queue( const QString & str ); void flush(); void embedPart( const QByteArray & contentId, const QString & url ); - void extraHead( const QString& str ); + void extraHead( const QString& str ); - private: +private: /** We own the HtmlWriters added to us! */ QList mWriters; - }; +}; } // namespace MessageViewer diff -Nru kdepim-4.12.97/messageviewer/htmlwriter/webkitparthtmlwriter.cpp kdepim-4.13.0/messageviewer/htmlwriter/webkitparthtmlwriter.cpp --- kdepim-4.12.97/messageviewer/htmlwriter/webkitparthtmlwriter.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/htmlwriter/webkitparthtmlwriter.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -50,116 +50,116 @@ using namespace MessageViewer; WebKitPartHtmlWriter::WebKitPartHtmlWriter( MailWebView * view, QObject * parent ) - : QObject( parent ), HtmlWriter(), - mHtmlView( view ), mState( Ended ) + : QObject( parent ), HtmlWriter(), + mHtmlView( view ), mState( Ended ) { - assert( view ); + assert( view ); } WebKitPartHtmlWriter::~WebKitPartHtmlWriter() { } void WebKitPartHtmlWriter::begin( const QString & css ) { - // The stylesheet is now included CSSHelper::htmlHead() - Q_UNUSED( css ); - if ( mState != Ended ) { - kWarning() << "begin() called on non-ended session!"; - reset(); - } - - mEmbeddedPartMap.clear(); - - // clear the widget: - mHtmlView->setUpdatesEnabled( false ); - mHtmlView->scrollUp( 10 ); + // The stylesheet is now included CSSHelper::htmlHead() + Q_UNUSED( css ); + if ( mState != Ended ) { + kWarning() << "begin() called on non-ended session!"; + reset(); + } + + mEmbeddedPartMap.clear(); + + // clear the widget: + mHtmlView->setUpdatesEnabled( false ); + mHtmlView->scrollUp( 10 ); #ifndef KDEPIM_NO_WEBKIT - // PENDING(marc) push into MailWebView - mHtmlView->load( QUrl() ); + // PENDING(marc) push into MailWebView + mHtmlView->load( QUrl() ); #endif - mState = Begun; + mState = Begun; } void WebKitPartHtmlWriter::end() { - if ( mState != Begun ) { - kWarning() << "Called on non-begun or queued session!"; - } - if(!mExtraHead.isEmpty()) { - insertExtraHead(); - mExtraHead.clear(); - } - mHtmlView->setHtml( mHtml, QUrl( QLatin1String("file:///") ) ); - mHtmlView->show(); - mHtml.clear(); + if ( mState != Begun ) { + kWarning() << "Called on non-begun or queued session!"; + } + if(!mExtraHead.isEmpty()) { + insertExtraHead(); + mExtraHead.clear(); + } + mHtmlView->setHtml( mHtml, QUrl( QLatin1String("file:///") ) ); + mHtmlView->show(); + mHtml.clear(); #ifndef KDEPIM_NO_WEBKIT - resolveCidUrls(); - mHtmlView->scamCheck(); + resolveCidUrls(); + mHtmlView->scamCheck(); #endif - mHtmlView->setUpdatesEnabled( true ); - mHtmlView->update(); - mState = Ended; - emit finished(); + mHtmlView->setUpdatesEnabled( true ); + mHtmlView->update(); + mState = Ended; + emit finished(); } void WebKitPartHtmlWriter::reset() { - if ( mState != Ended ) { - mHtml.clear(); - mState = Begun; // don't run into end()'s warning - end(); - mState = Ended; - } + if ( mState != Ended ) { + mHtml.clear(); + mState = Begun; // don't run into end()'s warning + end(); + mState = Ended; + } } void WebKitPartHtmlWriter::write( const QString & str ) { - if ( mState != Begun ) { - kWarning() << "Called in Ended or Queued state!"; - } - mHtml.append( str ); + if ( mState != Begun ) { + kWarning() << "Called in Ended or Queued state!"; + } + mHtml.append( str ); } void WebKitPartHtmlWriter::queue( const QString & str ) { - write( str ); + write( str ); } void WebKitPartHtmlWriter::flush() { - mState = Begun; // don't run into end()'s warning - end(); + mState = Begun; // don't run into end()'s warning + end(); } void WebKitPartHtmlWriter::embedPart( const QByteArray & contentId, const QString & contentURL ) { - mEmbeddedPartMap[QLatin1String(contentId)] = contentURL; + mEmbeddedPartMap[QLatin1String(contentId)] = contentURL; } void WebKitPartHtmlWriter::resolveCidUrls() { - // FIXME: instead of patching around in the HTML source, this should - // be replaced by a custom QNetworkAccessManager (for QWebView), or - // virtual loadResource() (for QTextBrowser) + // FIXME: instead of patching around in the HTML source, this should + // be replaced by a custom QNetworkAccessManager (for QWebView), or + // virtual loadResource() (for QTextBrowser) #ifndef KDEPIM_NO_WEBKIT - QWebElement root = mHtmlView->page()->mainFrame()->documentElement(); - QWebElementCollection images = root.findAll( QLatin1String("img") ); - QWebElementCollection::iterator end(images.end()); - for( QWebElementCollection::iterator it = images.begin(); it != end; ++it ) { - KUrl url( (*it).attribute( QLatin1String("src") ) ); - if ( url.protocol() == QLatin1String( "cid" ) ) { - EmbeddedPartMap::const_iterator cit = mEmbeddedPartMap.constFind( url.path() ); - if ( cit != mEmbeddedPartMap.constEnd() ) { - kDebug() << "Replacing" << url.prettyUrl() << "by" << cit.value(); - (*it).setAttribute( QLatin1String("src"), cit.value() ); - } + QWebElement root = mHtmlView->page()->mainFrame()->documentElement(); + QWebElementCollection images = root.findAll( QLatin1String("img") ); + QWebElementCollection::iterator end(images.end()); + for( QWebElementCollection::iterator it = images.begin(); it != end; ++it ) { + KUrl url( (*it).attribute( QLatin1String("src") ) ); + if ( url.protocol() == QLatin1String( "cid" ) ) { + EmbeddedPartMap::const_iterator cit = mEmbeddedPartMap.constFind( url.path() ); + if ( cit != mEmbeddedPartMap.constEnd() ) { + kDebug() << "Replacing" << url.prettyUrl() << "by" << cit.value(); + (*it).setAttribute( QLatin1String("src"), cit.value() ); + } + } } - } #endif } void WebKitPartHtmlWriter::insertExtraHead() { - const QString headTag(QLatin1String("")); - const int index = mHtml.indexOf(headTag); - if(index!=-1) { - mHtml.insert(index+headTag.length(),mExtraHead); - } + const QString headTag(QLatin1String("")); + const int index = mHtml.indexOf(headTag); + if(index!=-1) { + mHtml.insert(index+headTag.length(),mExtraHead); + } } void WebKitPartHtmlWriter::extraHead( const QString& str ) diff -Nru kdepim-4.12.97/messageviewer/htmlwriter/webkitparthtmlwriter.h kdepim-4.13.0/messageviewer/htmlwriter/webkitparthtmlwriter.h --- kdepim-4.12.97/messageviewer/htmlwriter/webkitparthtmlwriter.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/htmlwriter/webkitparthtmlwriter.h 2014-04-10 07:40:20.000000000 +0000 @@ -41,44 +41,44 @@ #include namespace MessageViewer { - class MailWebView; +class MailWebView; } namespace MessageViewer { class WebKitPartHtmlWriter : public QObject, public HtmlWriter { - Q_OBJECT + Q_OBJECT public: - explicit WebKitPartHtmlWriter( MailWebView * view, QObject * parent=0 ); - ~WebKitPartHtmlWriter(); + explicit WebKitPartHtmlWriter( MailWebView * view, QObject * parent=0 ); + ~WebKitPartHtmlWriter(); - void begin( const QString & cssDefs ); - void end(); - void reset(); - void write( const QString & str ); - void queue( const QString & str ); - void flush(); - void embedPart( const QByteArray & contentId, const QString & url ); - void extraHead( const QString& str ); + void begin( const QString & cssDefs ); + void end(); + void reset(); + void write( const QString & str ); + void queue( const QString & str ); + void flush(); + void embedPart( const QByteArray & contentId, const QString & url ); + void extraHead( const QString& str ); signals: - void finished(); + void finished(); private: - void resolveCidUrls(); - void insertExtraHead(); + void resolveCidUrls(); + void insertExtraHead(); private: - MailWebView * mHtmlView; - QString mHtml; - QString mExtraHead; - enum State { - Begun, - Queued, - Ended - } mState; - // Key is Content-Id, value is URL - typedef QMap EmbeddedPartMap; - EmbeddedPartMap mEmbeddedPartMap; + MailWebView * mHtmlView; + QString mHtml; + QString mExtraHead; + enum State { + Begun, + Queued, + Ended + } mState; + // Key is Content-Id, value is URL + typedef QMap EmbeddedPartMap; + EmbeddedPartMap mEmbeddedPartMap; }; } diff -Nru kdepim-4.12.97/messageviewer/notify/messageviewer.notifyrc kdepim-4.13.0/messageviewer/notify/messageviewer.notifyrc --- kdepim-4.12.97/messageviewer/notify/messageviewer.notifyrc 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/notify/messageviewer.notifyrc 2014-04-10 07:40:20.000000000 +0000 @@ -11,13 +11,15 @@ Comment[fi]=Viestikatselin Comment[fr]=Afficheur de messages Comment[hu]=Üzenetmegjelenítő +Comment[ia]=Visor de Message Comment[it]=Visualizzatore del messaggio Comment[nb]=Meldingsviser Comment[nds]=Narichtenkieker -Comment[nl]=MessageViewer +Comment[nl]=Viewer van meldingen Comment[pl]=Przeglądarka wiadomości Comment[pt]=Visualizador da Mensagem Comment[pt_BR]=Visualizador de mensagens +Comment[ru]=Окно просмотра письма Comment[sk]=Prehliadač správ Comment[sr]=Приказивач порука Comment[sr@ijekavian]=Приказивач порука @@ -50,6 +52,7 @@ Name[pl]=Ukończono pobieranie nowej listy do blokowania reklam Name[pt]=Transferência da nova lista de bloqueios completa Name[pt_BR]=Download da nova lista de bloqueio de anúncios concluído +Name[ru]=Загружен новый список блокировки рекламы Name[sk]=Nový zoznam Ad-Blocku hotový Name[sr]=Завршено преузимање нове Адблокове листе Name[sr@ijekavian]=Завршено преузимање нове Адблокове листе @@ -81,6 +84,7 @@ Comment[pl]=Ukończono pobieranie nowej listy do blokowania reklam Comment[pt]=A transferência da nova lista de bloqueios de anúncios terminou Comment[pt_BR]=Download da nova lista de bloqueio de anúncios concluído +Comment[ru]=Загружен новый список блокировки рекламы Comment[sk]=Nový zoznam Ad-Blocku hotový Comment[sr]=Завршено преузимање нове Адблокове листе Comment[sr@ijekavian]=Завршено преузимање нове Адблокове листе @@ -115,6 +119,7 @@ Name[pl]=Nieudane pobieranie nowej listy do blokowania reklam Name[pt]=Transferência da nova lista de bloqueios mal-sucedida Name[pt_BR]=Falha no download da nova lista de bloqueio de anúncios +Name[ru]=Не удалось загрузить список блокировки рекламы Name[sk]=Nový zoznam Ad-Blocku zlyhal Name[sr]=Пропало преузимање нове Адблокове листе Name[sr@ijekavian]=Пропало преузимање нове Адблокове листе @@ -146,6 +151,7 @@ Comment[pl]=Nieudane pobieranie nowej listy do blokowania reklam Comment[pt]=A transferência da nova lista de bloqueios de anúncios foi mal-sucedida Comment[pt_BR]=Falha no download da nova lista de bloqueio de anúncios +Comment[ru]=Не удалось загрузить список блокировки рекламы Comment[sk]=Nový zoznam Ad-Blocku zlyhal Comment[sr]=Пропало преузимање нове Адблокове листе Comment[sr@ijekavian]=Пропало преузимање нове Адблокове листе diff -Nru kdepim-4.12.97/messageviewer/tests/data/openpgp-encrypted-enigmail1.6.mbox kdepim-4.13.0/messageviewer/tests/data/openpgp-encrypted-enigmail1.6.mbox --- kdepim-4.12.97/messageviewer/tests/data/openpgp-encrypted-enigmail1.6.mbox 1970-01-01 00:00:00.000000000 +0000 +++ kdepim-4.13.0/messageviewer/tests/data/openpgp-encrypted-enigmail1.6.mbox 2014-04-10 07:40:20.000000000 +0000 @@ -0,0 +1,48 @@ +From you@you.com Sat, 29 Mar 2014 15:04:21 +0100 +FCC: imap://hefee%40netzguerilla.net@mail.netzguerilla.net/Sent +X-Identity-Key: id1 +X-Account-Key: account4 +Message-ID: <5336D2E5.6010602@you.com> +Date: Sat, 29 Mar 2014 15:04:21 +0100 +From: you +X-Mozilla-Draft-Info: internal/draft; vcard=0; receipt=0; DSN=0; uuencode=0 +User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Icedove/24.4.0 +MIME-Version: 1.0 +To: test@kolab.com +Subject: test +X-Enigmail-Version: 1.6 +X-Enigmail-Draft-Status: 515 +X-Enigmail-Draft-Status: 739 +Content-Type: multipart/encrypted; + protocol="application/pgp-encrypted"; + boundary="23VWJ4jAoB40SD17lh6TOBXK3fQSEGNu5" + +This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156) +--23VWJ4jAoB40SD17lh6TOBXK3fQSEGNu5 +Content-Type: application/pgp-encrypted +Content-Description: PGP/MIME version identification + +Version: 1 + +--23VWJ4jAoB40SD17lh6TOBXK3fQSEGNu5 +Content-Type: application/octet-stream; name="encrypted.asc" +Content-Description: OpenPGP encrypted message +Content-Disposition: inline; filename="encrypted.asc" + +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1 +Comment: Using GnuPG with Icedove - http://www.enigmail.net/ + +hIwDGJlthTT7oq0BA/9NtLLXbiIJVS6pOynwEeSznrQK7kYVla8RM43//JECCkGJ +azEaSBznabBv6epaFmQtVHLMXlCbZnMmW9loyqPBfMoAms6kKKBdG/jqhus89iXE ++seXngC233Va/gZMb2DxOqIokVNfj9tpR7xQ8wS/jHTDiLNc1GOQC7ku42z2bNLA +IQFRD/qbBFz89hU4wP4cYoAysOnEDojFrsrnCidTHJOJrndM6PPUtH/jQCyfr/EG +2tSpJwYKvmT6ly3yqaGLBtRPIxiv+dMe+7yw0t40qbjvvaTGavErEBJEKX5eWbTN +/sjajHpUHqs6SIiMheH9dr+WfzFONtVbPEgGRmOERhlgTl/nLo86AZpjJroIGKJJ +tTHCcoQGAWG+N7wrCE1RxR0kkMs4nRozj0TLu6ZyXMs+H063MewTPNxNAiQT1Nbi +udKWmfLBlxn06p+JDzUKxj8PFwObdbxTvACzbAvBY1aHMQ== +=mLl3 +-----END PGP MESSAGE----- + +--23VWJ4jAoB40SD17lh6TOBXK3fQSEGNu5-- + diff -Nru kdepim-4.12.97/messageviewer/tests/data/openpgp-encrypted-enigmail1.6.mbox.html kdepim-4.13.0/messageviewer/tests/data/openpgp-encrypted-enigmail1.6.mbox.html --- kdepim-4.12.97/messageviewer/tests/data/openpgp-encrypted-enigmail1.6.mbox.html 1970-01-01 00:00:00.000000000 +0000 +++ kdepim-4.13.0/messageviewer/tests/data/openpgp-encrypted-enigmail1.6.mbox.html 2014-04-10 07:40:20.000000000 +0000 @@ -0,0 +1,404 @@ + + + + + + <style> +div.header { + margin-bottom: 10pt ! important; +} + +table.textAtm { + margin-top: 10pt ! important; + margin-bottom: 10pt ! important; +} + +tr.textAtmH, +tr.textAtmB, +tr.rfc822B { + font-weight: normal ! important; +} + +tr.signInProgressH, +tr.rfc822H, +tr.encrH, +tr.signOkKeyOkH, +tr.signOkKeyBadH, +tr.signWarnH, +tr.signErrH { + font-weight: bold ! important; +} + +tr.textAtmH td, +tr.textAtmB td { + padding: 3px ! important; +} + +table.rfc822 { + width: 100% ! important; + border: solid 1px black ! important; + margin-top: 10pt ! important; + margin-bottom: 10pt ! important; +} + +table.textAtm, +table.encr, +table.signWarn, +table.signErr, +table.signOkKeyBad, +table.signOkKeyOk, +table.signInProgress, +div.fancy.header table { + width: 100% ! important; + border-width: 0px ! important; + line-height: normal; +} + +div.htmlWarn { + margin: 0px 5% ! important; + padding: 10px ! important; + text-align: left ! important; + line-height: normal; +} + +div.fancy.header > div { + font-weight: bold ! important; + padding: 4px ! important; + line-height: normal; +} + +div.fancy.header table { + padding: 2px ! important; + text-align: left ! important; + border-collapse: separate ! important; +} + +div.fancy.header table th { + font-family: "Sans Serif" ! important; + font-size: 0px ! important; + + padding: 0px ! important; + white-space: nowrap ! important; + border-spacing: 0px ! important; + text-align: left ! important; + vertical-align: top ! important; + background-color: #d6d2d0 ! important; + color: #221f1e ! important; + border: 1px ! important; +} + +div.fancy.header table td { + font-family: "Sans Serif" ! important; + font-size: 0px ! important; + + padding: 0px ! important; + border-spacing: 0px ! important; + text-align: left ! important; + vertical-align: top ! important; + width: 100% ! important; + background-color: #d6d2d0 ! important; + color: #221f1e ! important; + border: 1px ! important; +} + +div.fancy.header table a:hover { + background-color: transparent ! important; +} + +span.pimsmileytext { + position: absolute; + top: 0px; + left: 0px; + visibility: hidden; +} + +img.pimsmileyimg { +} + +div.quotelevelmark { + position: absolute; + margin-left:-10px; +} + +@media screen { + +body { + font-family: "Sans Serif" ! important; + font-size: 0px ! important; + color: #1f1c1b ! important; + background-color: #ffffff ! important; +} + +a { + color: #0057ae ! important; + text-decoration: none ! important; +} + +a.white { + color: white ! important; +} + +a.black { + color: black ! important; +} + +table.textAtm { background-color: #1f1c1b ! important; } + +tr.textAtmH { + background-color: #ffffff ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.textAtmB { + background-color: #ffffff ! important; +} + +table.signInProgress, +table.rfc822 { + background-color: #ffffff ! important; +} + +tr.signInProgressH, +tr.rfc822H { + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +table.encr { + background-color: #0069cc ! important; +} + +tr.encrH { + background-color: #0080ff ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.encrB { background-color: #e0f0ff ! important; } + +table.signOkKeyOk { + background-color: #33cc33 ! important; +} + +tr.signOkKeyOkH { + background-color: #40ff40 ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.signOkKeyOkB { background-color: #e8ffe8 ! important; } + +table.signOkKeyBad { + background-color: #cccc33 ! important; +} + +tr.signOkKeyBadH { + background-color: #ffff40 ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.signOkKeyBadB { background-color: #ffffe8 ! important; } + +table.signWarn { + background-color: #cccc33 ! important; +} + +tr.signWarnH { + background-color: #ffff40 ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.signWarnB { background-color: #ffffe8 ! important; } + +table.signErr { + background-color: #cc0000 ! important; +} + +tr.signErrH { + background-color: #ff0000 ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.signErrB { background-color: #ffe0e0 ! important; } + +div.htmlWarn { + border: 2px solid #ff4040 ! important; + line-height: normal; +} + +div.header { + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +div.fancy.header > div { + background-color: #43ace8 ! important; + color: #ffffff ! important; + border: solid #221f1e 1px ! important; + line-height: normal; +} + +div.fancy.header > div a[href] { color: #ffffff ! important; } + +div.fancy.header > div a[href]:hover { text-decoration: underline ! important; } + +div.fancy.header > div.spamheader { + background-color: #cdcdcd ! important; + border-top: 0px ! important; + padding: 3px ! important; + color: black ! important; + font-weight: bold ! important; + font-size: smaller ! important; +} + +div.fancy.header > table.outer { + background-color: #d6d2d0 ! important; + color: #221f1e ! important; + border-bottom: solid #221f1e 1px ! important; + border-left: solid #221f1e 1px ! important; + border-right: solid #221f1e 1px ! important; +} + +div.senderpic{ + padding: 0px ! important; + font-size:0.8em ! important; + border:1px solid #b3aba7 ! important; + background-color:#d6d2d0 ! important; +} + +div.senderstatus{ + text-align:center ! important; +} + +div.quotelevel1 { + color: #008000 ! important; + font-style: italic ! important; +} + +div.quotelevel2 { + color: #007000 ! important; + font-style: italic ! important; +} + +div.quotelevel3 { + color: #006000 ! important; + font-style: italic ! important; +} + +div.deepquotelevel1 { + color: #008000 ! important; + font-style: italic ! important; +} + +div.deepquotelevel2 { + color: #007000 ! important; + font-style: italic ! important; +} + +div.deepquotelevel3 { + color: #006000 ! important; + font-style: italic ! important; +} + +} +@media print { + +body { + font-family: "Sans Serif" ! important; + font-size: 9pt ! important; + color: #000000 ! important; + background-color: #ffffff ! important +} + +tr.textAtmH, +tr.signInProgressH, +tr.rfc822H, +tr.encrH, +tr.signOkKeyOkH, +tr.signOkKeyBadH, +tr.signWarnH, +tr.signErrH, +div.header { + font-family: "Sans Serif" ! important; + font-size: 9pt ! important; +} + +div.fancy.header > div { + background-color: #d6d2d0 ! important; + color: #221f1e ! important; + padding: 4px ! important; + border: solid #221f1e 1px ! important; + line-height: normal; +} + +div.fancy.header > div a[href] { color: #221f1e ! important; } + +div.fancy.header > table.outer{ + background-color: #d6d2d0 ! important; + color: #221f1e ! important; + border-bottom: solid #221f1e 1px ! important; + border-left: solid #221f1e 1px ! important; + border-right: solid #221f1e 1px ! important; +} + +div.spamheader { + display:none ! important; +} + +div.htmlWarn { + border: 2px solid #ffffff ! important; + line-height: normal; +} + +div.senderpic{ + font-size:0.8em ! important; + border:1px solid black ! important; + background-color:#d6d2d0 ! important; +} + +div.senderstatus{ + text-align:center ! important; +} + +div.noprint { + display:none ! important; +} + + +</style> + </head> + <body> + <div style="position: relative; word-wrap: break-word"> + <a name="att"/> + <div id="attachmentDiv"> + <table cellspacing="1" cellpadding="1" class="encr"> + <tr class="encrH"> + <td dir="ltr">Encrypted message</td> + </tr> + <tr class="encrB"> + <td> + <div style="position: relative; word-wrap: break-word"> + <a name="att"/> + <div id="attachmentDiv"> + <a name="att1"/> + <div id="attachmentDiv1"> + <div class="noquote"> + <div dir="ltr">test</div> + </div> + </div> + </div> + </div> + </td> + </tr> + <tr class="encrH"> + <td dir="ltr">End of encrypted message</td> + </tr> + </table> + </div> + </div> + </body> +</html> diff -Nru kdepim-4.12.97/messageviewer/tests/todoedittest.cpp kdepim-4.13.0/messageviewer/tests/todoedittest.cpp --- kdepim-4.12.97/messageviewer/tests/todoedittest.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/tests/todoedittest.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -69,7 +69,6 @@ //We can't test if because it loads from settings and in Jenkins it doesn't exist but here it exists //QVERIFY(edit.collection().isValid()); QVERIFY(!edit.message()); - QVERIFY(edit.messageUrlAkonadi().isEmpty()); QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit")); QVERIFY(noteedit); QCOMPARE(noteedit->text(), QString()); @@ -192,7 +191,7 @@ KMime::Message::Ptr msg(new KMime::Message); edit.setMessage(msg); QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit")); - QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection,QString))); + QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection))); QTest::keyClick(noteedit, Qt::Key_Enter); QCOMPARE(spy.count(), 0); } @@ -203,7 +202,7 @@ KMime::Message::Ptr msg(new KMime::Message); edit.setMessage(msg); QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit")); - QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection,QString))); + QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection))); noteedit->setText(QLatin1String(" ")); QTest::keyClick(noteedit, Qt::Key_Enter); QCOMPARE(spy.count(), 0); @@ -221,7 +220,7 @@ msg->subject(true)->fromUnicodeString(subject, "us-ascii"); edit.setMessage(msg); QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit")); - QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection,QString))); + QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection))); QTest::keyClick(noteedit, Qt::Key_Enter); QCOMPARE(spy.count(), 1); } @@ -234,7 +233,7 @@ msg->subject(true)->fromUnicodeString(subject, "us-ascii"); edit.setMessage(msg); QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit")); - QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection,QString))); + QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection))); QTest::keyClick(noteedit, Qt::Key_Enter); QCOMPARE(spy.count(), 1); KCalCore::Todo::Ptr todoPtr = spy.at(0).at(0).value<KCalCore::Todo::Ptr>(); @@ -249,11 +248,9 @@ QString subject = QLatin1String("Test Note"); msg->subject(true)->fromUnicodeString(subject, "us-ascii"); edit.setMessage(msg); - edit.setMessageUrlAkonadi(QLatin1String("foo")); QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit")); edit.slotCloseWidget(); QCOMPARE(noteedit->text(), QString()); - QCOMPARE(edit.messageUrlAkonadi(), QString()); QVERIFY(!edit.message()); } @@ -280,7 +277,7 @@ akonadicombobox->setCurrentIndex(3); Akonadi::Collection col = akonadicombobox->currentCollection(); QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit")); - QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection,QString))); + QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection))); QTest::keyClick(noteedit, Qt::Key_Enter); QCOMPARE(spy.count(), 1); QCOMPARE(spy.at(0).at(1).value<Akonadi::Collection>(), col); @@ -364,7 +361,7 @@ QString subject = QLatin1String("Test Note"); QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit")); noteedit->setText(subject); - QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection,QString))); + QSignalSpy spy(&edit, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection))); QTest::keyClick(noteedit, Qt::Key_Enter); QCOMPARE(spy.count(), 0); } @@ -394,16 +391,4 @@ QCOMPARE(noteedit->hasFocus(), true); } -void TodoEditTest::shouldClearUrlMessageWhenSwitchMessage() -{ - MessageViewer::TodoEdit edit; - KMime::Message::Ptr msg(new KMime::Message); - edit.setMessage(msg); - edit.setMessageUrlAkonadi(QLatin1String("test")); - QCOMPARE(edit.messageUrlAkonadi(), QLatin1String("test")); - KMime::Message::Ptr msg2(new KMime::Message); - edit.setMessage(msg2); - QCOMPARE(edit.messageUrlAkonadi(), QString()); -} - QTEST_KDEMAIN( TodoEditTest, GUI ) diff -Nru kdepim-4.12.97/messageviewer/tests/todoedittest.h kdepim-4.13.0/messageviewer/tests/todoedittest.h --- kdepim-4.12.97/messageviewer/tests/todoedittest.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/tests/todoedittest.h 2014-04-10 07:40:20.000000000 +0000 @@ -52,7 +52,6 @@ void shouldSaveCollectionSettingsWhenCloseWidget(); void shouldNotEmitTodoWhenMessageIsNull(); void shouldHaveLineEditFocus(); - void shouldClearUrlMessageWhenSwitchMessage(); void shouldEmitNotEmitTodoWhenTextTrimmedIsEmpty(); void shouldSaveCollectionSettingsWhenDeleteWidget(); void shouldSetFocusWhenWeCallTodoEdit(); diff -Nru kdepim-4.12.97/messageviewer/utils/iconnamecache.cpp kdepim-4.13.0/messageviewer/utils/iconnamecache.cpp --- kdepim-4.12.97/messageviewer/utils/iconnamecache.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/utils/iconnamecache.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -27,29 +27,29 @@ IconNameCache* IconNameCache::instance() { - return s_iconNameCache; + return s_iconNameCache; } bool IconNameCache::Entry::operator < ( const Entry &other ) const { - const int fileNameCompare = fileName.compare( other.fileName ); - if ( fileNameCompare != 0 ) - return fileNameCompare < 0; - else - return size < other.size; + const int fileNameCompare = fileName.compare( other.fileName ); + if ( fileNameCompare != 0 ) + return fileNameCompare < 0; + else + return size < other.size; } QString IconNameCache::iconPath( const QString &name, int size ) const { - Entry entry; - entry.fileName = name; - entry.size = size; + Entry entry; + entry.fileName = name; + entry.size = size; - if ( mCachedEntries.contains( entry ) ) - return mCachedEntries.value( entry ); + if ( mCachedEntries.contains( entry ) ) + return mCachedEntries.value( entry ); - const QString fileName = KIconLoader::global()->iconPath( name, size ); - mCachedEntries.insert( entry, fileName ); - return fileName; + const QString fileName = KIconLoader::global()->iconPath( name, size ); + mCachedEntries.insert( entry, fileName ); + return fileName; } } diff -Nru kdepim-4.12.97/messageviewer/utils/iconnamecache.h kdepim-4.13.0/messageviewer/utils/iconnamecache.h --- kdepim-4.12.97/messageviewer/utils/iconnamecache.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/utils/iconnamecache.h 2014-04-10 07:40:20.000000000 +0000 @@ -34,16 +34,16 @@ */ class MESSAGEVIEWER_EXPORT IconNameCache { - public: +public: static IconNameCache *instance(); QString iconPath( const QString &name, int size ) const; - private: +private: class Entry { - public: + public: QString fileName; int size; diff -Nru kdepim-4.12.97/messageviewer/utils/markmessagereadhandler.cpp kdepim-4.13.0/messageviewer/utils/markmessagereadhandler.cpp --- kdepim-4.12.97/messageviewer/utils/markmessagereadhandler.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/utils/markmessagereadhandler.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -32,9 +32,9 @@ class MarkMessageReadHandler::Private { - public: + public: Private( MarkMessageReadHandler *qq ) - : q( qq ) + : q( qq ) { } @@ -47,53 +47,53 @@ void MarkMessageReadHandler::Private::handleMessages() { - Akonadi::Item item = mItemQueue; + Akonadi::Item item = mItemQueue; - // mark as read - item.setFlag( Akonadi::MessageFlags::Seen ); - - Akonadi::ItemModifyJob *modifyJob = new Akonadi::ItemModifyJob( item, q ); - modifyJob->disableRevisionCheck(); - modifyJob->setIgnorePayload( true ); - sListItem->removeAll(item); + // mark as read + item.setFlag( Akonadi::MessageFlags::Seen ); + + Akonadi::ItemModifyJob *modifyJob = new Akonadi::ItemModifyJob( item, q ); + modifyJob->disableRevisionCheck(); + modifyJob->setIgnorePayload( true ); + sListItem->removeAll(item); } MarkMessageReadHandler::MarkMessageReadHandler( QObject *parent ) - : QObject( parent ), d( new Private( this ) ) + : QObject( parent ), d( new Private( this ) ) { - d->mTimer.setSingleShot( true ); - connect( &d->mTimer, SIGNAL(timeout()), this, SLOT(handleMessages()) ); + d->mTimer.setSingleShot( true ); + connect( &d->mTimer, SIGNAL(timeout()), this, SLOT(handleMessages()) ); } MarkMessageReadHandler::~MarkMessageReadHandler() { - if( d->mTimer.isActive() ) - d->mTimer.stop(); - delete d; + if( d->mTimer.isActive() ) + d->mTimer.stop(); + delete d; } void MarkMessageReadHandler::setItem( const Akonadi::Item &item ) { - if ( sListItem->contains(item) || d->mItemQueue == item || item.hasFlag(Akonadi::MessageFlags::Queued) ) - return; - d->mTimer.stop(); - - sListItem->removeAll(d->mItemQueue); - d->mItemQueue = item; - sListItem->append(item); - if ( item.hasFlag( Akonadi::MessageFlags::Seen ) ) - return; - - if ( MessageViewer::GlobalSettings::self()->delayedMarkAsRead() ) { - const int delayedMarkTime = MessageViewer::GlobalSettings::self()->delayedMarkTime(); - if ( delayedMarkTime != 0 ) { - d->mTimer.start( delayedMarkTime * 1000 ); - } - else { - d->handleMessages(); + if ( sListItem->contains(item) || d->mItemQueue == item || item.hasFlag(Akonadi::MessageFlags::Queued) ) + return; + d->mTimer.stop(); + + sListItem->removeAll(d->mItemQueue); + d->mItemQueue = item; + sListItem->append(item); + if ( item.hasFlag( Akonadi::MessageFlags::Seen ) ) + return; + + if ( MessageViewer::GlobalSettings::self()->delayedMarkAsRead() ) { + const int delayedMarkTime = MessageViewer::GlobalSettings::self()->delayedMarkTime(); + if ( delayedMarkTime != 0 ) { + d->mTimer.start( delayedMarkTime * 1000 ); + } + else { + d->handleMessages(); + } } - } } #include "moc_markmessagereadhandler.cpp" diff -Nru kdepim-4.12.97/messageviewer/utils/markmessagereadhandler.h kdepim-4.13.0/messageviewer/utils/markmessagereadhandler.h --- kdepim-4.12.97/messageviewer/utils/markmessagereadhandler.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/utils/markmessagereadhandler.h 2014-04-10 07:40:20.000000000 +0000 @@ -35,9 +35,9 @@ */ class MESSAGEVIEWER_EXPORT MarkMessageReadHandler : public QObject, public AbstractMessageLoadedHandler { - Q_OBJECT + Q_OBJECT - public: +public: /** * Creates a new mark message read handler. * @@ -55,7 +55,7 @@ */ void setItem( const Akonadi::Item &item ); - private: +private: //@cond PRIVATE class Private; Private* const d; diff -Nru kdepim-4.12.97/messageviewer/utils/util.cpp kdepim-4.13.0/messageviewer/utils/util.cpp --- kdepim-4.12.97/messageviewer/utils/util.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/utils/util.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -78,61 +78,61 @@ bool Util::checkOverwrite( const KUrl &url, QWidget *w ) { - if ( KIO::NetAccess::exists( url, KIO::NetAccess::DestinationSide, w ) ) { - if ( KMessageBox::Cancel == KMessageBox::warningContinueCancel( - w, - i18n( "A file named \"%1\" already exists. " - "Are you sure you want to overwrite it?", url.prettyUrl() ), - i18n( "Overwrite File?" ), - KStandardGuiItem::overwrite() ) ) - return false; - } - return true; + if ( KIO::NetAccess::exists( url, KIO::NetAccess::DestinationSide, w ) ) { + if ( KMessageBox::Cancel == KMessageBox::warningContinueCancel( + w, + i18n( "A file named \"%1\" already exists. " + "Are you sure you want to overwrite it?", url.prettyUrl() ), + i18n( "Overwrite File?" ), + KStandardGuiItem::overwrite() ) ) + return false; + } + return true; } QString Util::fileNameForMimetype( const QString &mimeType, int iconSize, const QString &fallbackFileName1, const QString &fallbackFileName2 ) { - QString fileName; - QString tMimeType = mimeType; + QString fileName; + QString tMimeType = mimeType; - // convert non-registered types to registered types - if ( mimeType == QLatin1String( "application/x-vnd.kolab.contact" ) ) { - tMimeType = QLatin1String( "text/x-vcard" ); - } else if ( mimeType == QLatin1String( "application/x-vnd.kolab.event" ) ) { - tMimeType = QLatin1String( "application/x-vnd.akonadi.calendar.event" ); - } else if ( mimeType == QLatin1String( "application/x-vnd.kolab.task" ) ) { - tMimeType = QLatin1String( "application/x-vnd.akonadi.calendar.todo" ); - } else if ( mimeType == QLatin1String( "application/x-vnd.kolab.journal" ) ) { - tMimeType = QLatin1String( "application/x-vnd.akonadi.calendar.journal" ); - } else if ( mimeType == QLatin1String( "application/x-vnd.kolab.note" ) ) { - tMimeType = QLatin1String( "application/x-vnd.akonadi.note" ); - } - KMimeType::Ptr mime = KMimeType::mimeType( tMimeType, KMimeType::ResolveAliases ); - if ( mime ) { - fileName = mime->iconName(); - } else { - fileName = QLatin1String( "unknown" ); - if ( !tMimeType.isEmpty() ) { - kWarning() << "unknown mimetype" << tMimeType; - } - } - //WorkAround for #199083 - if(fileName == QLatin1String("text-vcard")) { - fileName = QLatin1String("text-x-vcard"); - } - if ( fileName.isEmpty() ) { - fileName = fallbackFileName1; - if ( fileName.isEmpty() ) { - fileName = fallbackFileName2; + // convert non-registered types to registered types + if ( mimeType == QLatin1String( "application/x-vnd.kolab.contact" ) ) { + tMimeType = QLatin1String( "text/x-vcard" ); + } else if ( mimeType == QLatin1String( "application/x-vnd.kolab.event" ) ) { + tMimeType = QLatin1String( "application/x-vnd.akonadi.calendar.event" ); + } else if ( mimeType == QLatin1String( "application/x-vnd.kolab.task" ) ) { + tMimeType = QLatin1String( "application/x-vnd.akonadi.calendar.todo" ); + } else if ( mimeType == QLatin1String( "application/x-vnd.kolab.journal" ) ) { + tMimeType = QLatin1String( "application/x-vnd.akonadi.calendar.journal" ); + } else if ( mimeType == QLatin1String( "application/x-vnd.kolab.note" ) ) { + tMimeType = QLatin1String( "application/x-vnd.akonadi.note" ); + } + KMimeType::Ptr mime = KMimeType::mimeType( tMimeType, KMimeType::ResolveAliases ); + if ( mime ) { + fileName = mime->iconName(); + } else { + fileName = QLatin1String( "unknown" ); + if ( !tMimeType.isEmpty() ) { + kWarning() << "unknown mimetype" << tMimeType; + } } - if ( !fileName.isEmpty() ) { - fileName = KMimeType::findByPath( QLatin1String("/tmp/") + fileName, 0, true )->iconName(); + //WorkAround for #199083 + if(fileName == QLatin1String("text-vcard")) { + fileName = QLatin1String("text-x-vcard"); + } + if ( fileName.isEmpty() ) { + fileName = fallbackFileName1; + if ( fileName.isEmpty() ) { + fileName = fallbackFileName2; + } + if ( !fileName.isEmpty() ) { + fileName = KMimeType::findByPath( QLatin1String("/tmp/") + fileName, 0, true )->iconName(); + } } - } - return IconNameCache::instance()->iconPath( fileName, iconSize ); + return IconNameCache::instance()->iconPath( fileName, iconSize ); } #if defined Q_WS_WIN || defined Q_WS_MACX @@ -142,437 +142,437 @@ bool Util::handleUrlWithQDesktopServices( const KUrl& url ) { #if defined Q_WS_WIN || defined Q_WS_MACX - QDesktopServices::openUrl( url ); - return true; + QDesktopServices::openUrl( url ); + return true; #else - Q_UNUSED( url ); - return false; + Q_UNUSED( url ); + return false; #endif } QList<KMime::Content*> Util::allContents( const KMime::Content *message ) { - KMime::Content::List result; - KMime::Content *child = MessageCore::NodeHelper::firstChild( message ); - if ( child ) { - result += child; - result += allContents( child ); - } - KMime::Content *next = MessageCore::NodeHelper::nextSibling( message ); - if ( next ) { - result += next; - result += allContents( next ); - } + KMime::Content::List result; + KMime::Content *child = MessageCore::NodeHelper::firstChild( message ); + if ( child ) { + result += child; + result += allContents( child ); + } + KMime::Content *next = MessageCore::NodeHelper::nextSibling( message ); + if ( next ) { + result += next; + result += allContents( next ); + } - return result; + return result; } QList<KMime::Content*> Util::extractAttachments( const KMime::Message *message ) { - const KMime::Content::List contents = allContents( message ); - KMime::Content::List result; - for ( KMime::Content::List::const_iterator it = contents.constBegin(); - it != contents.constEnd(); ) { - KMime::Content* content = *it; - if ( content->contentDisposition()->filename().trimmed().isEmpty() && - ( content->contentType()->name().trimmed().isEmpty() || - content == message ) ) { - ++it; - } else { - result <<( *it ); - ++it; + const KMime::Content::List contents = allContents( message ); + KMime::Content::List result; + for ( KMime::Content::List::const_iterator it = contents.constBegin(); + it != contents.constEnd(); ) { + KMime::Content* content = *it; + if ( content->contentDisposition()->filename().trimmed().isEmpty() && + ( content->contentType()->name().trimmed().isEmpty() || + content == message ) ) { + ++it; + } else { + result <<( *it ); + ++it; + } } - } - return result; + return result; } bool Util::saveContents( QWidget *parent, const QList<KMime::Content*> &contents ) { - KUrl url, dirUrl; - const bool multiple = (contents.count() > 1); - if ( multiple ) { - // get the dir - dirUrl = KFileDialog::getExistingDirectoryUrl( KUrl( QLatin1String("kfiledialog:///saveAttachment") ), - parent, - i18n( "Save Attachments To" ) ); - if ( !dirUrl.isValid() ) { - return false; - } - - // we may not get a slash-terminated url out of KFileDialog - dirUrl.adjustPath( KUrl::AddTrailingSlash ); - } else { - // only one item, get the desired filename - KMime::Content *content = contents.first(); - QString fileName = NodeHelper::fileName( content ); - fileName = MessageCore::StringUtil::cleanFileName( fileName ); - if ( fileName.isEmpty() ) { - fileName = i18nc( "filename for an unnamed attachment", "attachment.1" ); - } - KUrl pathUrl = KUrl( QLatin1String("kfiledialog:///saveAttachment/")); - pathUrl.addPath(fileName); - url = KFileDialog::getSaveUrl( pathUrl , - QString(), - parent, - i18n( "Save Attachment" ) ); - if ( url.isEmpty() ) { - return false; - } - } - - QMap< QString, int > renameNumbering; - - bool globalResult = true; - int unnamedAtmCount = 0; - PimCommon::RenameFileDialog::RenameFileDialogResult result = PimCommon::RenameFileDialog::RENAMEFILE_IGNORE; - foreach( KMime::Content *content, contents ) { - KUrl curUrl; - if ( !dirUrl.isEmpty() ) { - curUrl = dirUrl; - QString fileName = MessageViewer::NodeHelper::fileName( content ); - fileName = MessageCore::StringUtil::cleanFileName( fileName ); - if ( fileName.isEmpty() ) { - ++unnamedAtmCount; - fileName = i18nc( "filename for the %1-th unnamed attachment", - "attachment.%1", unnamedAtmCount ); - } - curUrl.setFileName( fileName ); + KUrl url, dirUrl; + const bool multiple = (contents.count() > 1); + if ( multiple ) { + // get the dir + dirUrl = KFileDialog::getExistingDirectoryUrl( KUrl( QLatin1String("kfiledialog:///saveAttachment") ), + parent, + i18n( "Save Attachments To" ) ); + if ( !dirUrl.isValid() ) { + return false; + } + + // we may not get a slash-terminated url out of KFileDialog + dirUrl.adjustPath( KUrl::AddTrailingSlash ); } else { - curUrl = url; + // only one item, get the desired filename + KMime::Content *content = contents.first(); + QString fileName = NodeHelper::fileName( content ); + fileName = MessageCore::StringUtil::cleanFileName( fileName ); + if ( fileName.isEmpty() ) { + fileName = i18nc( "filename for an unnamed attachment", "attachment.1" ); + } + KUrl pathUrl = KUrl( QLatin1String("kfiledialog:///saveAttachment/")); + pathUrl.addPath(fileName); + url = KFileDialog::getSaveUrl( pathUrl , + QString(), + parent, + i18n( "Save Attachment" ) ); + if ( url.isEmpty() ) { + return false; + } } - if ( !curUrl.isEmpty() ) { - //Bug #312954 - if (multiple && (curUrl.fileName() == QLatin1String("smime.p7s")) ) { - continue; - } - // Rename the file if we have already saved one with the same name: - // try appending a number before extension (e.g. "pic.jpg" => "pic_2.jpg") - QString origFile = curUrl.fileName(); - QString file = origFile; - - while ( renameNumbering.contains(file) ) { - file = origFile; - int num = renameNumbering[file] + 1; - int dotIdx = file.lastIndexOf(QLatin1Char('.')); - file = file.insert( (dotIdx>=0) ? dotIdx : file.length(), QLatin1String("_") + QString::number(num) ); - } - curUrl.setFileName(file); - - // Increment the counter for both the old and the new filename - if ( !renameNumbering.contains(origFile)) - renameNumbering[origFile] = 1; - else - renameNumbering[origFile]++; - - if ( file != origFile ) { - if ( !renameNumbering.contains(file)) - renameNumbering[file] = 1; - else - renameNumbering[file]++; - } - - - if( !(result == PimCommon::RenameFileDialog::RENAMEFILE_OVERWRITEALL || - result == PimCommon::RenameFileDialog::RENAMEFILE_IGNOREALL )) { - if ( KIO::NetAccess::exists( curUrl, KIO::NetAccess::DestinationSide, parent ) ) { - PimCommon::RenameFileDialog *dlg = new PimCommon::RenameFileDialog(curUrl, multiple, parent); - result = static_cast<PimCommon::RenameFileDialog::RenameFileDialogResult>(dlg->exec()); - if ( result == PimCommon::RenameFileDialog::RENAMEFILE_IGNORE || - result == PimCommon::RenameFileDialog::RENAMEFILE_IGNOREALL) - { - delete dlg; - continue; - } - else if ( result == PimCommon::RenameFileDialog::RENAMEFILE_RENAME ) - { - curUrl = dlg->newName(); - } - delete dlg; - } - } - // save - if( result != PimCommon::RenameFileDialog::RENAMEFILE_IGNOREALL ) { - const bool result = saveContent( parent, content, curUrl ); - if ( !result ) - globalResult = result; - } + + QMap< QString, int > renameNumbering; + + bool globalResult = true; + int unnamedAtmCount = 0; + PimCommon::RenameFileDialog::RenameFileDialogResult result = PimCommon::RenameFileDialog::RENAMEFILE_IGNORE; + foreach( KMime::Content *content, contents ) { + KUrl curUrl; + if ( !dirUrl.isEmpty() ) { + curUrl = dirUrl; + QString fileName = MessageViewer::NodeHelper::fileName( content ); + fileName = MessageCore::StringUtil::cleanFileName( fileName ); + if ( fileName.isEmpty() ) { + ++unnamedAtmCount; + fileName = i18nc( "filename for the %1-th unnamed attachment", + "attachment.%1", unnamedAtmCount ); + } + curUrl.setFileName( fileName ); + } else { + curUrl = url; + } + if ( !curUrl.isEmpty() ) { + //Bug #312954 + if (multiple && (curUrl.fileName() == QLatin1String("smime.p7s")) ) { + continue; + } + // Rename the file if we have already saved one with the same name: + // try appending a number before extension (e.g. "pic.jpg" => "pic_2.jpg") + QString origFile = curUrl.fileName(); + QString file = origFile; + + while ( renameNumbering.contains(file) ) { + file = origFile; + int num = renameNumbering[file] + 1; + int dotIdx = file.lastIndexOf(QLatin1Char('.')); + file = file.insert( (dotIdx>=0) ? dotIdx : file.length(), QLatin1String("_") + QString::number(num) ); + } + curUrl.setFileName(file); + + // Increment the counter for both the old and the new filename + if ( !renameNumbering.contains(origFile)) + renameNumbering[origFile] = 1; + else + renameNumbering[origFile]++; + + if ( file != origFile ) { + if ( !renameNumbering.contains(file)) + renameNumbering[file] = 1; + else + renameNumbering[file]++; + } + + + if( !(result == PimCommon::RenameFileDialog::RENAMEFILE_OVERWRITEALL || + result == PimCommon::RenameFileDialog::RENAMEFILE_IGNOREALL )) { + if ( KIO::NetAccess::exists( curUrl, KIO::NetAccess::DestinationSide, parent ) ) { + PimCommon::RenameFileDialog *dlg = new PimCommon::RenameFileDialog(curUrl, multiple, parent); + result = static_cast<PimCommon::RenameFileDialog::RenameFileDialogResult>(dlg->exec()); + if ( result == PimCommon::RenameFileDialog::RENAMEFILE_IGNORE || + result == PimCommon::RenameFileDialog::RENAMEFILE_IGNOREALL) + { + delete dlg; + continue; + } + else if ( result == PimCommon::RenameFileDialog::RENAMEFILE_RENAME ) + { + curUrl = dlg->newName(); + } + delete dlg; + } + } + // save + if( result != PimCommon::RenameFileDialog::RENAMEFILE_IGNOREALL ) { + const bool result = saveContent( parent, content, curUrl ); + if ( !result ) + globalResult = result; + } + } } - } - return globalResult; + return globalResult; } bool Util::saveContent( QWidget *parent, KMime::Content* content, const KUrl& url ) { - // FIXME: This is all horribly broken. First of all, creating a NodeHelper and then immediatley - // reading out the encryption/signature state will not work at all. - // Then, topLevel() will not work for attachments that are inside encrypted parts. - // What should actually be done is either passing in an ObjectTreeParser that has already - // parsed the message, or creating an OTP here (which would have the downside that the - // password dialog for decrypting messages is shown twice) + // FIXME: This is all horribly broken. First of all, creating a NodeHelper and then immediatley + // reading out the encryption/signature state will not work at all. + // Then, topLevel() will not work for attachments that are inside encrypted parts. + // What should actually be done is either passing in an ObjectTreeParser that has already + // parsed the message, or creating an OTP here (which would have the downside that the + // password dialog for decrypting messages is shown twice) #if 0 // totally broken - KMime::Content *topContent = content->topLevel(); - MessageViewer::NodeHelper *mNodeHelper = new MessageViewer::NodeHelper; - bool bSaveEncrypted = false; - bool bEncryptedParts = mNodeHelper->encryptionState( content ) != MessageViewer::KMMsgNotEncrypted; - if( bEncryptedParts ) - if( KMessageBox::questionYesNo( parent, - i18n( "The part %1 of the message is encrypted. Do you want to keep the encryption when saving?", - url.fileName() ), - i18n( "KMail Question" ), KGuiItem(i18n("Keep Encryption")), KGuiItem(i18n("Do Not Keep")) ) == - KMessageBox::Yes ) - bSaveEncrypted = true; - - bool bSaveWithSig = true; - if(mNodeHelper->signatureState( content ) != MessageViewer::KMMsgNotSigned ) - if( KMessageBox::questionYesNo( parent, - i18n( "The part %1 of the message is signed. Do you want to keep the signature when saving?", - url.fileName() ), - i18n( "KMail Question" ), KGuiItem(i18n("Keep Signature")), KGuiItem(i18n("Do Not Keep")) ) != - KMessageBox::Yes ) - bSaveWithSig = false; - - QByteArray data; - if( bSaveEncrypted || !bEncryptedParts) { - KMime::Content *dataNode = content; - QByteArray rawDecryptedBody; - bool gotRawDecryptedBody = false; - if ( !bSaveWithSig ) { - if ( topContent->contentType()->mimeType() == "multipart/signed" ) { - // carefully look for the part that is *not* the signature part: - if ( ObjectTreeParser::findType( topContent, "application/pgp-signature", true, false ) ) { - dataNode = ObjectTreeParser::findTypeNot( topContent, "application", "pgp-signature", true, false ); - } else if ( ObjectTreeParser::findType( topContent, "application/pkcs7-mime" , true, false ) ) { - dataNode = ObjectTreeParser::findTypeNot( topContent, "application", "pkcs7-mime", true, false ); - } else { - dataNode = ObjectTreeParser::findTypeNot( topContent, "multipart", "", true, false ); + KMime::Content *topContent = content->topLevel(); + MessageViewer::NodeHelper *mNodeHelper = new MessageViewer::NodeHelper; + bool bSaveEncrypted = false; + bool bEncryptedParts = mNodeHelper->encryptionState( content ) != MessageViewer::KMMsgNotEncrypted; + if( bEncryptedParts ) + if( KMessageBox::questionYesNo( parent, + i18n( "The part %1 of the message is encrypted. Do you want to keep the encryption when saving?", + url.fileName() ), + i18n( "KMail Question" ), KGuiItem(i18n("Keep Encryption")), KGuiItem(i18n("Do Not Keep")) ) == + KMessageBox::Yes ) + bSaveEncrypted = true; + + bool bSaveWithSig = true; + if(mNodeHelper->signatureState( content ) != MessageViewer::KMMsgNotSigned ) + if( KMessageBox::questionYesNo( parent, + i18n( "The part %1 of the message is signed. Do you want to keep the signature when saving?", + url.fileName() ), + i18n( "KMail Question" ), KGuiItem(i18n("Keep Signature")), KGuiItem(i18n("Do Not Keep")) ) != + KMessageBox::Yes ) + bSaveWithSig = false; + + QByteArray data; + if( bSaveEncrypted || !bEncryptedParts) { + KMime::Content *dataNode = content; + QByteArray rawDecryptedBody; + bool gotRawDecryptedBody = false; + if ( !bSaveWithSig ) { + if ( topContent->contentType()->mimeType() == "multipart/signed" ) { + // carefully look for the part that is *not* the signature part: + if ( ObjectTreeParser::findType( topContent, "application/pgp-signature", true, false ) ) { + dataNode = ObjectTreeParser::findTypeNot( topContent, "application", "pgp-signature", true, false ); + } else if ( ObjectTreeParser::findType( topContent, "application/pkcs7-mime" , true, false ) ) { + dataNode = ObjectTreeParser::findTypeNot( topContent, "application", "pkcs7-mime", true, false ); + } else { + dataNode = ObjectTreeParser::findTypeNot( topContent, "multipart", "", true, false ); + } + } else { + EmptySource emptySource; + ObjectTreeParser otp( &emptySource, 0, 0, false, false ); + + // process this node and all it's siblings and descendants + mNodeHelper->setNodeUnprocessed( dataNode, true ); + otp.parseObjectTree( dataNode ); + + rawDecryptedBody = otp.rawDecryptedBody(); + gotRawDecryptedBody = true; + } } - } else { - EmptySource emptySource; - ObjectTreeParser otp( &emptySource, 0, 0, false, false ); - - // process this node and all it's siblings and descendants - mNodeHelper->setNodeUnprocessed( dataNode, true ); - otp.parseObjectTree( dataNode ); - - rawDecryptedBody = otp.rawDecryptedBody(); - gotRawDecryptedBody = true; - } - } - QByteArray cstr = gotRawDecryptedBody - ? rawDecryptedBody - : dataNode->decodedContent(); - data = KMime::CRLFtoLF( cstr ); - } + QByteArray cstr = gotRawDecryptedBody + ? rawDecryptedBody + : dataNode->decodedContent(); + data = KMime::CRLFtoLF( cstr ); + } #else - const QByteArray data = content->decodedContent(); - kWarning() << "Port the encryption/signature handling when saving a KMime::Content."; + const QByteArray data = content->decodedContent(); + kWarning() << "Port the encryption/signature handling when saving a KMime::Content."; #endif - QDataStream ds; - QFile file; - KTemporaryFile tf; - if ( url.isLocalFile() ) - { - // save directly - file.setFileName( url.toLocalFile() ); - if ( !file.open( QIODevice::WriteOnly ) ) + QDataStream ds; + QFile file; + KTemporaryFile tf; + if ( url.isLocalFile() ) { - KMessageBox::error( parent, - i18nc( "1 = file name, 2 = error string", - "<qt>Could not write to the file<br><filename>%1</filename><br><br>%2", - file.fileName(), - file.errorString() ), - i18n( "Error saving attachment" ) ); - return false; - } - - const int permissions = MessageViewer::Util::getWritePermissions(); - if ( permissions >= 0 ) - fchmod( file.handle(), permissions ); - - ds.setDevice( &file ); - } else - { - // tmp file for upload - tf.open(); - ds.setDevice( &tf ); - } - - const int bytesWritten = ds.writeRawData( data.data(), data.size() ); - if ( bytesWritten != data.size() ) { - QFile *f = static_cast<QFile *>( ds.device() ); - KMessageBox::error( parent, - i18nc( "1 = file name, 2 = error string", - "<qt>Could not write to the file<br><filename>%1</filename><br><br>%2", - f->fileName(), - f->errorString() ), - i18n( "Error saving attachment" ) ); - // Remove the newly created empty or partial file - f->remove(); - return false; - } + // save directly + file.setFileName( url.toLocalFile() ); + if ( !file.open( QIODevice::WriteOnly ) ) + { + KMessageBox::error( parent, + i18nc( "1 = file name, 2 = error string", + "<qt>Could not write to the file<br><filename>%1</filename><br><br>%2", + file.fileName(), + file.errorString() ), + i18n( "Error saving attachment" ) ); + return false; + } + + const int permissions = MessageViewer::Util::getWritePermissions(); + if ( permissions >= 0 ) + fchmod( file.handle(), permissions ); + + ds.setDevice( &file ); + } else + { + // tmp file for upload + tf.open(); + ds.setDevice( &tf ); + } + + const int bytesWritten = ds.writeRawData( data.data(), data.size() ); + if ( bytesWritten != data.size() ) { + QFile *f = static_cast<QFile *>( ds.device() ); + KMessageBox::error( parent, + i18nc( "1 = file name, 2 = error string", + "<qt>Could not write to the file<br><filename>%1</filename><br><br>%2", + f->fileName(), + f->errorString() ), + i18n( "Error saving attachment" ) ); + // Remove the newly created empty or partial file + f->remove(); + return false; + } - if ( !url.isLocalFile() ) + if ( !url.isLocalFile() ) { - // QTemporaryFile::fileName() is only defined while the file is open - QString tfName = tf.fileName(); - tf.close(); - if ( !KIO::NetAccess::upload( tfName, url, parent ) ) + // QTemporaryFile::fileName() is only defined while the file is open + QString tfName = tf.fileName(); + tf.close(); + if ( !KIO::NetAccess::upload( tfName, url, parent ) ) { - KMessageBox::error( parent, - i18nc( "1 = file name, 2 = error string", - "<qt>Could not write to the file<br><filename>%1</filename><br><br>%2", - url.prettyUrl(), - KIO::NetAccess::lastErrorString() ), - i18n( "Error saving attachment" ) ); - return false; + KMessageBox::error( parent, + i18nc( "1 = file name, 2 = error string", + "<qt>Could not write to the file<br><filename>%1</filename><br><br>%2", + url.prettyUrl(), + KIO::NetAccess::lastErrorString() ), + i18n( "Error saving attachment" ) ); + return false; } } - else - file.close(); + else + file.close(); #if 0 - mNodeHelper->removeTempFiles(); - delete mNodeHelper; + mNodeHelper->removeTempFiles(); + delete mNodeHelper; #endif - return true; + return true; } int Util::getWritePermissions() { - // #79685, #232001 by default use the umask the user defined, but let it be configurable - if ( MessageCore::GlobalSettings::self()->disregardUmask() ) { - return S_IRUSR | S_IWUSR; - } else { - return -1; - } + // #79685, #232001 by default use the umask the user defined, but let it be configurable + if ( MessageCore::GlobalSettings::self()->disregardUmask() ) { + return S_IRUSR | S_IWUSR; + } else { + return -1; + } } bool Util::saveAttachments( const KMime::Content::List& contents, QWidget *parent ) { - if ( contents.isEmpty() ) { - KMessageBox::information( parent, i18n( "Found no attachments to save." ) ); - return false; - } + if ( contents.isEmpty() ) { + KMessageBox::information( parent, i18n( "Found no attachments to save." ) ); + return false; + } - return Util::saveContents( parent, contents ); + return Util::saveContents( parent, contents ); } bool Util::saveMessageInMbox( const QList<Akonadi::Item>& retrievedMsgs, QWidget *parent, bool appendMessages ) { - QString fileName; - if ( retrievedMsgs.isEmpty() ) - return true; - const Akonadi::Item msgBase = retrievedMsgs.first(); + QString fileName; + if ( retrievedMsgs.isEmpty() ) + return true; + const Akonadi::Item msgBase = retrievedMsgs.first(); + + if( msgBase.hasPayload<KMime::Message::Ptr>() ) + fileName = MessageCore::StringUtil::cleanFileName(MessageViewer::NodeHelper::cleanSubject ( msgBase.payload<KMime::Message::Ptr>().get() ).trimmed() ); + else + fileName = i18n("message"); + + if ( !fileName.endsWith( QLatin1String( ".mbox" ) ) ) + fileName += QLatin1String(".mbox"); + + const QString filter = i18n( "*.mbox|email messages (*.mbox)\n*|all files (*)" ); + QPointer<KFileDialog> dlg = new KFileDialog(KUrl::fromPath( fileName ), filter, parent); + dlg->setCaption(i18np("Save Message", "Save Messages", retrievedMsgs.count())); + dlg->setMode(KFile::File|KFile::LocalOnly); + dlg->setOperationMode(KFileDialog::Saving); + if( !appendMessages ) + dlg->setConfirmOverwrite(true); + if (dlg->exec()) { + KUrl url = dlg->selectedUrl(); + if ( url.isEmpty() ) { + delete dlg; + return true; + } + + const QString localFileName = url.toLocalFile(); + if ( localFileName.isEmpty() ) { + delete dlg; + return true; + } + + if( !appendMessages ) { + QFile::remove(localFileName); + } + + KMBox::MBox mbox; + if ( !mbox.load( localFileName ) ) { + if( appendMessages ) { + KMessageBox::error( parent, i18n("File %1 could not be loaded.",localFileName) , i18n( "Error loading message" ) ); + } else { + KMessageBox::error( parent, i18n("File %1 could not be created.",localFileName) , i18n( "Error saving message" ) ); + } + delete dlg; + return false; + } + foreach ( const Akonadi::Item &item, retrievedMsgs ) { + if ( item.hasPayload<KMime::Message::Ptr>() ) { + mbox.appendMessage( item.payload<KMime::Message::Ptr>() ); + } + } - if( msgBase.hasPayload<KMime::Message::Ptr>() ) - fileName = MessageCore::StringUtil::cleanFileName(MessageViewer::NodeHelper::cleanSubject ( msgBase.payload<KMime::Message::Ptr>().get() ).trimmed() ); - else - fileName = i18n("message"); - - if ( !fileName.endsWith( QLatin1String( ".mbox" ) ) ) - fileName += QLatin1String(".mbox"); - - const QString filter = i18n( "*.mbox|email messages (*.mbox)\n*|all files (*)" ); - QPointer<KFileDialog> dlg = new KFileDialog(KUrl::fromPath( fileName ), filter, parent); - dlg->setCaption(i18np("Save Message", "Save Messages", retrievedMsgs.count())); - dlg->setMode(KFile::File|KFile::LocalOnly); - dlg->setOperationMode(KFileDialog::Saving); - if( !appendMessages ) - dlg->setConfirmOverwrite(true); - if (dlg->exec()) { - KUrl url = dlg->selectedUrl(); - if ( url.isEmpty() ) { - delete dlg; - return true; - } - - const QString localFileName = url.toLocalFile(); - if ( localFileName.isEmpty() ) { - delete dlg; - return true; - } - - if( !appendMessages ) { - QFile::remove(localFileName); - } - - KMBox::MBox mbox; - if ( !mbox.load( localFileName ) ) { - if( appendMessages ) { - KMessageBox::error( parent, i18n("File %1 could not be loaded.",localFileName) , i18n( "Error loading message" ) ); - } else { - KMessageBox::error( parent, i18n("File %1 could not be created.",localFileName) , i18n( "Error saving message" ) ); - } - delete dlg; - return false; - } - foreach ( const Akonadi::Item &item, retrievedMsgs ) { - if ( item.hasPayload<KMime::Message::Ptr>() ) { - mbox.appendMessage( item.payload<KMime::Message::Ptr>() ); - } - } - - if ( !mbox.save() ) { - KMessageBox::error( parent, i18n("We cannot save message.") , i18n( "Error saving message" ) ); - delete dlg; - return false; - } - } - delete dlg; - return true; + if ( !mbox.save() ) { + KMessageBox::error( parent, i18n("We cannot save message.") , i18n( "Error saving message" ) ); + delete dlg; + return false; + } + } + delete dlg; + return true; } bool Util::speakSelectedText( const QString& text, QWidget *parent) { - if(text.isEmpty()) - return false; + if(text.isEmpty()) + return false; - // If KTTSD not running, start it. - if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(QLatin1String("org.kde.kttsd"))) - { - QString error; - if (KToolInvocation::startServiceByDesktopName(QLatin1String("kttsd"), QStringList(), &error)) + // If KTTSD not running, start it. + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(QLatin1String("org.kde.kttsd"))) { - KMessageBox::error(parent, i18n( "Starting Jovie Text-to-Speech Service Failed"), error ); - return false; + QString error; + if (KToolInvocation::startServiceByDesktopName(QLatin1String("kttsd"), QStringList(), &error)) + { + KMessageBox::error(parent, i18n( "Starting Jovie Text-to-Speech Service Failed"), error ); + return false; + } } - } - QDBusInterface ktts(QLatin1String("org.kde.kttsd"), QLatin1String("/KSpeech"), QLatin1String("org.kde.KSpeech")); - ktts.asyncCall(QLatin1String("say"), text, 0); - return true; + QDBusInterface ktts(QLatin1String("org.kde.kttsd"), QLatin1String("/KSpeech"), QLatin1String("org.kde.KSpeech")); + ktts.asyncCall(QLatin1String("say"), text, 0); + return true; } KAction* Util::createAppAction(const KService::Ptr& service, bool singleOffer, QActionGroup *actionGroup, QObject *parent ) { - QString actionName(service->name().replace(QLatin1Char('&'), QLatin1String("&&"))); - if (singleOffer) { - actionName = i18n("Open &with %1", actionName); - } else { - actionName = i18nc("@item:inmenu Open With, %1 is application name", "%1", actionName); - } - - KAction *act = new KAction(parent); - act->setIcon(KIcon(service->icon())); - act->setText(actionName); - actionGroup->addAction( act ); - act->setData(QVariant::fromValue(service)); - return act; + QString actionName(service->name().replace(QLatin1Char('&'), QLatin1String("&&"))); + if (singleOffer) { + actionName = i18n("Open &with %1", actionName); + } else { + actionName = i18nc("@item:inmenu Open With, %1 is application name", "%1", actionName); + } + + KAction *act = new KAction(parent); + act->setIcon(KIcon(service->icon())); + act->setText(actionName); + actionGroup->addAction( act ); + act->setData(QVariant::fromValue(service)); + return act; } KMimeType::Ptr Util::mimetype(const QString& name) { - // consider the filename if mimetype cannot be found by content-type - KMimeType::Ptr mimeType = KMimeType::findByPath( name, 0, true /* no disk access */ ); - if ( mimeType->name() == QLatin1String("application/octet-stream") ) { - // consider the attachment's contents if neither the Content-Type header - // nor the filename give us a clue - mimeType = KMimeType::findByFileContent( name ); - } - return mimeType; + // consider the filename if mimetype cannot be found by content-type + KMimeType::Ptr mimeType = KMimeType::findByPath( name, 0, true /* no disk access */ ); + if ( mimeType->name() == QLatin1String("application/octet-stream") ) { + // consider the attachment's contents if neither the Content-Type header + // nor the filename give us a clue + mimeType = KMimeType::findByFileContent( name ); + } + return mimeType; } diff -Nru kdepim-4.12.97/messageviewer/utils/util.h kdepim-4.13.0/messageviewer/utils/util.h --- kdepim-4.12.97/messageviewer/utils/util.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/utils/util.h 2014-04-10 07:40:20.000000000 +0000 @@ -50,12 +50,12 @@ class KAction; namespace KMime { - class Content; - class Message; +class Content; +class Message; } namespace Akonadi { - class Item; +class Item; } namespace MessageViewer { @@ -66,42 +66,42 @@ */ namespace Util { - /** +/** * Describes the type of the displayed message. This depends on the MIME structure * of the mail and on whether HTML mode is enabled (which is decided by htmlMail()) */ - enum HtmlMode { - Normal, ///< A normal plaintext message, non-multipart - Html, ///< A HTML message, non-multipart - MultipartPlain, ///< A multipart/alternative message, the plain text part is currently displayed - MultipartHtml ///< A multipart/altervative message, the HTML part is currently displayed - }; +enum HtmlMode { + Normal, ///< A normal plaintext message, non-multipart + Html, ///< A HTML message, non-multipart + MultipartPlain, ///< A multipart/alternative message, the plain text part is currently displayed + MultipartHtml ///< A multipart/altervative message, the HTML part is currently displayed +}; - // return true if we should proceed, false if we should abort - bool MESSAGEVIEWER_EXPORT checkOverwrite( const KUrl &url, QWidget *w ); +// return true if we should proceed, false if we should abort +bool MESSAGEVIEWER_EXPORT checkOverwrite( const KUrl &url, QWidget *w ); - /** +/** * Delegates opening a URL to the QDesktopServices mechanisms for that * on Windows and MacOSX. * Returns false if it did nothing (such as on other platforms). */ - bool MESSAGEVIEWER_EXPORT handleUrlWithQDesktopServices( const KUrl& url ); +bool MESSAGEVIEWER_EXPORT handleUrlWithQDesktopServices( const KUrl& url ); - /** +/** * evaluates GlobalSettings->disregardUmask() * and returns resulting permissions for storing files * @return specific file permissions or -1 for default permissions */ - int MESSAGEVIEWER_EXPORT getWritePermissions(); +int MESSAGEVIEWER_EXPORT getWritePermissions(); - QList<KMime::Content*> MESSAGEVIEWER_EXPORT allContents( const KMime::Content *message ); - QList<KMime::Content*> MESSAGEVIEWER_EXPORT extractAttachments( const KMime::Message *message ); - bool MESSAGEVIEWER_EXPORT saveContents( QWidget *parent, - const QList<KMime::Content*> &contents ); - bool MESSAGEVIEWER_EXPORT saveContent( QWidget *parent, KMime::Content* content, - const KUrl& url ); +QList<KMime::Content*> MESSAGEVIEWER_EXPORT allContents( const KMime::Content *message ); +QList<KMime::Content*> MESSAGEVIEWER_EXPORT extractAttachments( const KMime::Message *message ); +bool MESSAGEVIEWER_EXPORT saveContents( QWidget *parent, + const QList<KMime::Content*> &contents ); +bool MESSAGEVIEWER_EXPORT saveContent( QWidget *parent, KMime::Content* content, + const KUrl& url ); - /** +/** * Finds the filename of an icon based on the given mimetype or filenames. * * Always use this functions when looking up icon names for mime types, don't use @@ -117,20 +117,20 @@ * Example: "test.zip" * @return the full file name of the icon file */ - QString MESSAGEVIEWER_EXPORT fileNameForMimetype( const QString &mimeType, int iconSize, - const QString &fallbackFileName1 = QString(), - const QString &fallbackFileName2 = QString() ); - bool MESSAGEVIEWER_EXPORT saveMessageInMbox( const QList<Akonadi::Item>& retrievedMsgs, QWidget*parent, bool appendMessages = false); +QString MESSAGEVIEWER_EXPORT fileNameForMimetype( const QString &mimeType, int iconSize, + const QString &fallbackFileName1 = QString(), + const QString &fallbackFileName2 = QString() ); +bool MESSAGEVIEWER_EXPORT saveMessageInMbox( const QList<Akonadi::Item>& retrievedMsgs, QWidget*parent, bool appendMessages = false); - bool MESSAGEVIEWER_EXPORT saveAttachments( const KMime::Content::List& contents, QWidget *parent ); +bool MESSAGEVIEWER_EXPORT saveAttachments( const KMime::Content::List& contents, QWidget *parent ); - bool MESSAGEVIEWER_EXPORT speakSelectedText( const QString& text, QWidget *parent); - MESSAGEVIEWER_EXPORT KAction* createAppAction(const KService::Ptr& service, bool singleOffer, QActionGroup *actionGroup, QObject *parent ); +bool MESSAGEVIEWER_EXPORT speakSelectedText( const QString& text, QWidget *parent); +MESSAGEVIEWER_EXPORT KAction* createAppAction(const KService::Ptr& service, bool singleOffer, QActionGroup *actionGroup, QObject *parent ); - /** +/** * Search mimetype from filename when mimetype is empty or application/octet-stream **/ - MESSAGEVIEWER_EXPORT KMimeType::Ptr mimetype(const QString& name); +MESSAGEVIEWER_EXPORT KMimeType::Ptr mimetype(const QString& name); } } diff -Nru kdepim-4.12.97/messageviewer/viewer/attachmentstrategy.cpp kdepim-4.13.0/messageviewer/viewer/attachmentstrategy.cpp --- kdepim-4.12.97/messageviewer/viewer/attachmentstrategy.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/attachmentstrategy.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -46,18 +46,18 @@ static AttachmentStrategy::Display smartDisplay( KMime::Content *node ) { - if ( node->contentDisposition()->disposition() == KMime::Headers::CDinline ) - // explict "inline" disposition: - return AttachmentStrategy::Inline; - if ( MessageCore::NodeHelper::isAttachment( node ) ) - // explicit "attachment" disposition: + if ( node->contentDisposition()->disposition() == KMime::Headers::CDinline ) + // explict "inline" disposition: + return AttachmentStrategy::Inline; + if ( MessageCore::NodeHelper::isAttachment( node ) ) + // explicit "attachment" disposition: + return AttachmentStrategy::AsIcon; + if ( node->contentType()->isText() && + node->contentDisposition()->filename().trimmed().isEmpty() && + node->contentType()->name().trimmed().isEmpty() ) + // text/* w/o filename parameter: + return AttachmentStrategy::Inline; return AttachmentStrategy::AsIcon; - if ( node->contentType()->isText() && - node->contentDisposition()->filename().trimmed().isEmpty() && - node->contentType()->name().trimmed().isEmpty() ) - // text/* w/o filename parameter: - return AttachmentStrategy::Inline; - return AttachmentStrategy::AsIcon; } // @@ -66,25 +66,25 @@ // class IconicAttachmentStrategy : public AttachmentStrategy { - friend class AttachmentStrategy; + friend class AttachmentStrategy; protected: - IconicAttachmentStrategy() : AttachmentStrategy() {} - virtual ~IconicAttachmentStrategy() {} + IconicAttachmentStrategy() : AttachmentStrategy() {} + virtual ~IconicAttachmentStrategy() {} public: - const char * name() const { return "iconic"; } - const AttachmentStrategy * next() const { return smart(); } - const AttachmentStrategy * prev() const { return headerOnly(); } - - bool inlineNestedMessages() const { return false; } - Display defaultDisplay( KMime::Content * node ) const { - if ( node->contentType()->isText() && - node->contentDisposition()->filename().trimmed().isEmpty() && - node->contentType()->name().trimmed().isEmpty() ) - // text/* w/o filename parameter: - return Inline; - return AsIcon; - } + const char * name() const { return "iconic"; } + const AttachmentStrategy * next() const { return smart(); } + const AttachmentStrategy * prev() const { return headerOnly(); } + + bool inlineNestedMessages() const { return false; } + Display defaultDisplay( KMime::Content * node ) const { + if ( node->contentType()->isText() && + node->contentDisposition()->filename().trimmed().isEmpty() && + node->contentType()->name().trimmed().isEmpty() ) + // text/* w/o filename parameter: + return Inline; + return AsIcon; + } }; // @@ -95,20 +95,20 @@ // class SmartAttachmentStrategy : public AttachmentStrategy { - friend class AttachmentStrategy; + friend class AttachmentStrategy; protected: - SmartAttachmentStrategy() : AttachmentStrategy() {} - virtual ~SmartAttachmentStrategy() {} + SmartAttachmentStrategy() : AttachmentStrategy() {} + virtual ~SmartAttachmentStrategy() {} public: - const char * name() const { return "smart"; } - const AttachmentStrategy * next() const { return inlined(); } - const AttachmentStrategy * prev() const { return iconic(); } - - bool inlineNestedMessages() const { return true; } - Display defaultDisplay( KMime::Content * node ) const { - return smartDisplay( node ); - } + const char * name() const { return "smart"; } + const AttachmentStrategy * next() const { return inlined(); } + const AttachmentStrategy * prev() const { return iconic(); } + + bool inlineNestedMessages() const { return true; } + Display defaultDisplay( KMime::Content * node ) const { + return smartDisplay( node ); + } }; // @@ -117,18 +117,18 @@ // class InlinedAttachmentStrategy : public AttachmentStrategy { - friend class AttachmentStrategy; + friend class AttachmentStrategy; protected: - InlinedAttachmentStrategy() : AttachmentStrategy() {} - virtual ~InlinedAttachmentStrategy() {} + InlinedAttachmentStrategy() : AttachmentStrategy() {} + virtual ~InlinedAttachmentStrategy() {} public: - const char * name() const { return "inlined"; } - const AttachmentStrategy * next() const { return hidden(); } - const AttachmentStrategy * prev() const { return smart(); } + const char * name() const { return "inlined"; } + const AttachmentStrategy * next() const { return hidden(); } + const AttachmentStrategy * prev() const { return smart(); } - bool inlineNestedMessages() const { return true; } - Display defaultDisplay( KMime::Content * ) const { return Inline; } + bool inlineNestedMessages() const { return true; } + Display defaultDisplay( KMime::Content * ) const { return Inline; } }; // @@ -137,67 +137,67 @@ // class HiddenAttachmentStrategy : public AttachmentStrategy { - friend class AttachmentStrategy; + friend class AttachmentStrategy; protected: - HiddenAttachmentStrategy() : AttachmentStrategy() {} - virtual ~HiddenAttachmentStrategy() {} + HiddenAttachmentStrategy() : AttachmentStrategy() {} + virtual ~HiddenAttachmentStrategy() {} public: - const char * name() const { return "hidden"; } - const AttachmentStrategy * next() const { return headerOnly(); } - const AttachmentStrategy * prev() const { return inlined(); } - - bool inlineNestedMessages() const { return false; } - Display defaultDisplay( KMime::Content * node ) const { - if ( node->contentType()->isText() && - node->contentDisposition()->filename().trimmed().isEmpty() && - node->contentType()->name().trimmed().isEmpty() ) - // text/* w/o filename parameter: - return Inline; - if (!node->parent()) - return Inline; - - if ( node->parent() && node->parent()->contentType()->isMultipart() && - node->parent()->contentType()->subType() == "related" ) - return Inline; + const char * name() const { return "hidden"; } + const AttachmentStrategy * next() const { return headerOnly(); } + const AttachmentStrategy * prev() const { return inlined(); } + + bool inlineNestedMessages() const { return false; } + Display defaultDisplay( KMime::Content * node ) const { + if ( node->contentType()->isText() && + node->contentDisposition()->filename().trimmed().isEmpty() && + node->contentType()->name().trimmed().isEmpty() ) + // text/* w/o filename parameter: + return Inline; + if (!node->parent()) + return Inline; + + if ( node->parent() && node->parent()->contentType()->isMultipart() && + node->parent()->contentType()->subType() == "related" ) + return Inline; - return None; - } + return None; + } }; class HeaderOnlyAttachmentStrategy : public AttachmentStrategy { - friend class AttachmentStrategy; + friend class AttachmentStrategy; protected: - HeaderOnlyAttachmentStrategy() : AttachmentStrategy() {} - virtual ~HeaderOnlyAttachmentStrategy() {} + HeaderOnlyAttachmentStrategy() : AttachmentStrategy() {} + virtual ~HeaderOnlyAttachmentStrategy() {} public: - const char * name() const { return "headerOnly"; } - const AttachmentStrategy * next() const { return iconic(); } - const AttachmentStrategy * prev() const { return hidden(); } - - bool inlineNestedMessages() const { - return true; - } - - Display defaultDisplay( KMime::Content * node ) const { - if ( NodeHelper::isInEncapsulatedMessage( node ) ) { - return smartDisplay( node ); - } - - NodeHelper::AttachmentDisplayInfo info = NodeHelper::attachmentDisplayInfo( node ); - if ( info.displayInHeader ) { - // The entire point about this attachment strategy: Hide attachments in the body that are - // already displayed in the attachment quick list - return None; - } else { - return smartDisplay( node ); - } - } - - virtual bool requiresAttachmentListInHeader() const { - return true; - } + const char * name() const { return "headerOnly"; } + const AttachmentStrategy * next() const { return iconic(); } + const AttachmentStrategy * prev() const { return hidden(); } + + bool inlineNestedMessages() const { + return true; + } + + Display defaultDisplay( KMime::Content * node ) const { + if ( NodeHelper::isInEncapsulatedMessage( node ) ) { + return smartDisplay( node ); + } + + NodeHelper::AttachmentDisplayInfo info = NodeHelper::attachmentDisplayInfo( node ); + if ( info.displayInHeader ) { + // The entire point about this attachment strategy: Hide attachments in the body that are + // already displayed in the attachment quick list + return None; + } else { + return smartDisplay( node ); + } + } + + virtual bool requiresAttachmentListInHeader() const { + return true; + } }; // @@ -213,28 +213,28 @@ } const AttachmentStrategy * AttachmentStrategy::create( Type type ) { - switch ( type ) { - case Iconic: return iconic(); - case Smart: return smart(); - case Inlined: return inlined(); - case Hidden: return hidden(); - case HeaderOnly: return headerOnly(); - } - kFatal() << "Unknown attachment startegy ( type ==" - << (int)type << ") requested!"; - return 0; // make compiler happy + switch ( type ) { + case Iconic: return iconic(); + case Smart: return smart(); + case Inlined: return inlined(); + case Hidden: return hidden(); + case HeaderOnly: return headerOnly(); + } + kFatal() << "Unknown attachment startegy ( type ==" + << (int)type << ") requested!"; + return 0; // make compiler happy } const AttachmentStrategy * AttachmentStrategy::create( const QString & type ) { - const QString lowerType = type.toLower(); - if ( lowerType == QLatin1String( "iconic" ) ) return iconic(); - //if ( lowerType == "smart" ) return smart(); // not needed, see below - if ( lowerType == QLatin1String( "inlined" ) ) return inlined(); - if ( lowerType == QLatin1String( "hidden" ) ) return hidden(); - if ( lowerType == QLatin1String( "headeronly" ) ) return headerOnly(); - // don't kFatal here, b/c the strings are user-provided - // (KConfig), so fail gracefully to the default: - return smart(); + const QString lowerType = type.toLower(); + if ( lowerType == QLatin1String( "iconic" ) ) return iconic(); + //if ( lowerType == "smart" ) return smart(); // not needed, see below + if ( lowerType == QLatin1String( "inlined" ) ) return inlined(); + if ( lowerType == QLatin1String( "hidden" ) ) return hidden(); + if ( lowerType == QLatin1String( "headeronly" ) ) return headerOnly(); + // don't kFatal here, b/c the strings are user-provided + // (KConfig), so fail gracefully to the default: + return smart(); } static const AttachmentStrategy * iconicStrategy = 0; @@ -244,34 +244,34 @@ static const AttachmentStrategy * headerOnlyStrategy = 0; const AttachmentStrategy * AttachmentStrategy::iconic() { - if ( !iconicStrategy ) - iconicStrategy = new IconicAttachmentStrategy(); - return iconicStrategy; + if ( !iconicStrategy ) + iconicStrategy = new IconicAttachmentStrategy(); + return iconicStrategy; } const AttachmentStrategy * AttachmentStrategy::smart() { - if ( !smartStrategy ) - smartStrategy = new SmartAttachmentStrategy(); - return smartStrategy; + if ( !smartStrategy ) + smartStrategy = new SmartAttachmentStrategy(); + return smartStrategy; } const AttachmentStrategy * AttachmentStrategy::inlined() { - if ( !inlinedStrategy ) - inlinedStrategy = new InlinedAttachmentStrategy(); - return inlinedStrategy; + if ( !inlinedStrategy ) + inlinedStrategy = new InlinedAttachmentStrategy(); + return inlinedStrategy; } const AttachmentStrategy * AttachmentStrategy::hidden() { - if ( !hiddenStrategy ) - hiddenStrategy = new HiddenAttachmentStrategy(); - return hiddenStrategy; + if ( !hiddenStrategy ) + hiddenStrategy = new HiddenAttachmentStrategy(); + return hiddenStrategy; } const AttachmentStrategy* AttachmentStrategy::headerOnly() { - if ( !headerOnlyStrategy ) - headerOnlyStrategy = new HeaderOnlyAttachmentStrategy(); - return headerOnlyStrategy; + if ( !headerOnlyStrategy ) + headerOnlyStrategy = new HeaderOnlyAttachmentStrategy(); + return headerOnlyStrategy; } } diff -Nru kdepim-4.12.97/messageviewer/viewer/attachmentstrategy.h kdepim-4.13.0/messageviewer/viewer/attachmentstrategy.h --- kdepim-4.12.97/messageviewer/viewer/attachmentstrategy.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/attachmentstrategy.h 2014-04-10 07:40:20.000000000 +0000 @@ -38,7 +38,7 @@ class QString; namespace KMime { - class Content; +class Content; } namespace MessageViewer { @@ -46,43 +46,43 @@ class MESSAGEVIEWER_EXPORT AttachmentStrategy { protected: - AttachmentStrategy(); - virtual ~AttachmentStrategy(); + AttachmentStrategy(); + virtual ~AttachmentStrategy(); public: - // - // Factory methods: - // - enum Type { Iconic, Smart, Inlined, Hidden, HeaderOnly }; - - static const AttachmentStrategy * create( Type type ); - static const AttachmentStrategy * create( const QString & type ); - - static const AttachmentStrategy * iconic(); - static const AttachmentStrategy * smart(); - static const AttachmentStrategy * inlined(); - static const AttachmentStrategy * hidden(); - static const AttachmentStrategy * headerOnly(); - - // - // Navigation methods: - // - - virtual const char * name() const = 0; - virtual const AttachmentStrategy * next() const = 0; - virtual const AttachmentStrategy * prev() const = 0; - - // - // Bahavioural: - // - - enum Display { None, AsIcon, Inline }; - - virtual bool inlineNestedMessages() const = 0; - virtual Display defaultDisplay( KMime::Content * node ) const = 0; - virtual bool requiresAttachmentListInHeader() const { - return false; - } + // + // Factory methods: + // + enum Type { Iconic, Smart, Inlined, Hidden, HeaderOnly }; + + static const AttachmentStrategy * create( Type type ); + static const AttachmentStrategy * create( const QString & type ); + + static const AttachmentStrategy * iconic(); + static const AttachmentStrategy * smart(); + static const AttachmentStrategy * inlined(); + static const AttachmentStrategy * hidden(); + static const AttachmentStrategy * headerOnly(); + + // + // Navigation methods: + // + + virtual const char * name() const = 0; + virtual const AttachmentStrategy * next() const = 0; + virtual const AttachmentStrategy * prev() const = 0; + + // + // Bahavioural: + // + + enum Display { None, AsIcon, Inline }; + + virtual bool inlineNestedMessages() const = 0; + virtual Display defaultDisplay( KMime::Content * node ) const = 0; + virtual bool requiresAttachmentListInHeader() const { + return false; + } }; } diff -Nru kdepim-4.12.97/messageviewer/viewer/bodypartformatter.cpp kdepim-4.13.0/messageviewer/viewer/bodypartformatter.cpp --- kdepim-4.12.97/messageviewer/viewer/bodypartformatter.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/bodypartformatter.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -46,85 +46,85 @@ using namespace MessageViewer; namespace { - class AnyTypeBodyPartFormatter - : public BodyPartFormatter, - public MessageViewer::Interface::BodyPartFormatter { +class AnyTypeBodyPartFormatter + : public BodyPartFormatter, + public MessageViewer::Interface::BodyPartFormatter { static const AnyTypeBodyPartFormatter * self; - public: +public: Result format( Interface::BodyPart *, HtmlWriter * ) const { - kDebug() << "Acting as a Interface::BodyPartFormatter!"; - return AsIcon; + kDebug() << "Acting as a Interface::BodyPartFormatter!"; + return AsIcon; } // unhide the overload with three arguments using MessageViewer::Interface::BodyPartFormatter::format; bool process( ObjectTreeParser *, KMime::Content *, ProcessResult & result ) const { - result.setNeverDisplayInline( true ); - return false; + result.setNeverDisplayInline( true ); + return false; } static const ::BodyPartFormatter * create() { - if ( !self ) - self = new AnyTypeBodyPartFormatter(); - return self; + if ( !self ) + self = new AnyTypeBodyPartFormatter(); + return self; } - }; +}; - const AnyTypeBodyPartFormatter * AnyTypeBodyPartFormatter::self = 0; +const AnyTypeBodyPartFormatter * AnyTypeBodyPartFormatter::self = 0; - class ImageTypeBodyPartFormatter : public BodyPartFormatter { +class ImageTypeBodyPartFormatter : public BodyPartFormatter { static const ImageTypeBodyPartFormatter * self; - public: +public: bool process( ObjectTreeParser *, KMime::Content *, ProcessResult & result ) const { - result.setIsImage( true ); - return false; + result.setIsImage( true ); + return false; } static const BodyPartFormatter * create() { - if ( !self ) - self = new ImageTypeBodyPartFormatter(); - return self; + if ( !self ) + self = new ImageTypeBodyPartFormatter(); + return self; } - }; +}; - const ImageTypeBodyPartFormatter * ImageTypeBodyPartFormatter::self = 0; +const ImageTypeBodyPartFormatter * ImageTypeBodyPartFormatter::self = 0; #define CREATE_BODY_PART_FORMATTER(subtype) \ - class subtype##BodyPartFormatter : public BodyPartFormatter { \ + class subtype##BodyPartFormatter : public BodyPartFormatter { \ static const subtype##BodyPartFormatter * self; \ - public: \ + public: \ bool process( ObjectTreeParser *, KMime::Content *, ProcessResult & ) const; \ static const BodyPartFormatter * create() { \ - if ( !self ) \ - self = new subtype##BodyPartFormatter(); \ - return self; \ - } \ - }; \ - \ - const subtype##BodyPartFormatter * subtype##BodyPartFormatter::self; \ - \ - bool subtype##BodyPartFormatter::process( ObjectTreeParser * otp, KMime::Content * node, ProcessResult & result ) const { \ + if ( !self ) \ + self = new subtype##BodyPartFormatter(); \ + return self; \ +} \ +}; \ + \ + const subtype##BodyPartFormatter * subtype##BodyPartFormatter::self; \ + \ + bool subtype##BodyPartFormatter::process( ObjectTreeParser * otp, KMime::Content * node, ProcessResult & result ) const { \ return otp->process##subtype##Subtype( node, result ); \ - } - - - CREATE_BODY_PART_FORMATTER(TextPlain) - CREATE_BODY_PART_FORMATTER(TextHtml) - //CREATE_BODY_PART_FORMATTER(TextEnriched) - - CREATE_BODY_PART_FORMATTER(ApplicationOctetStream) - CREATE_BODY_PART_FORMATTER(ApplicationPkcs7Mime) - CREATE_BODY_PART_FORMATTER(ApplicationChiasmusText) - //CREATE_BODY_PART_FORMATTER(ApplicationPgp) +} - CREATE_BODY_PART_FORMATTER(MessageRfc822) - CREATE_BODY_PART_FORMATTER(MultiPartMixed) - CREATE_BODY_PART_FORMATTER(MultiPartAlternative) - CREATE_BODY_PART_FORMATTER(MultiPartSigned) - CREATE_BODY_PART_FORMATTER(MultiPartEncrypted) +CREATE_BODY_PART_FORMATTER(TextPlain) +CREATE_BODY_PART_FORMATTER(TextHtml) +//CREATE_BODY_PART_FORMATTER(TextEnriched) + +CREATE_BODY_PART_FORMATTER(ApplicationOctetStream) +CREATE_BODY_PART_FORMATTER(ApplicationPkcs7Mime) +CREATE_BODY_PART_FORMATTER(ApplicationChiasmusText) +//CREATE_BODY_PART_FORMATTER(ApplicationPgp) + +CREATE_BODY_PART_FORMATTER(MessageRfc822) + +CREATE_BODY_PART_FORMATTER(MultiPartMixed) +CREATE_BODY_PART_FORMATTER(MultiPartAlternative) +CREATE_BODY_PART_FORMATTER(MultiPartSigned) +CREATE_BODY_PART_FORMATTER(MultiPartEncrypted) - typedef TextPlainBodyPartFormatter ApplicationPgpBodyPartFormatter; +typedef TextPlainBodyPartFormatter ApplicationPgpBodyPartFormatter; #undef CREATE_BODY_PART_FORMATTER @@ -132,55 +132,55 @@ // FIXME: port some more BodyPartFormatters to Interface::BodyPartFormatters void BodyPartFormatterFactoryPrivate::messageviewer_create_builtin_bodypart_formatters( BodyPartFormatterFactoryPrivate::TypeRegistry * reg ) { - if ( !reg ) return; - (*reg)["application"]["octet-stream"] = new AnyTypeBodyPartFormatter(); + if ( !reg ) return; + (*reg)["application"]["octet-stream"] = new AnyTypeBodyPartFormatter(); } typedef const BodyPartFormatter * (*BodyPartFormatterCreator)(); struct SubtypeBuiltin { - const char * subtype; - BodyPartFormatterCreator create; + const char * subtype; + BodyPartFormatterCreator create; }; static const SubtypeBuiltin applicationSubtypeBuiltins[] = { - { "octet-stream", &ApplicationOctetStreamBodyPartFormatter::create }, - { "pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create }, - { "x-pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create }, - { "vnd.de.bund.bsi.chiasmus-text", &ApplicationChiasmusTextBodyPartFormatter::create }, - { "pgp", &ApplicationPgpBodyPartFormatter::create }, + { "octet-stream", &ApplicationOctetStreamBodyPartFormatter::create }, + { "pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create }, + { "x-pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create }, + { "vnd.de.bund.bsi.chiasmus-text", &ApplicationChiasmusTextBodyPartFormatter::create }, + { "pgp", &ApplicationPgpBodyPartFormatter::create }, }; static const SubtypeBuiltin textSubtypeBuiltins[] = { - { "html", &TextHtmlBodyPartFormatter::create }, - //{ "enriched", &TextEnrichedBodyPartFormatter::create }, - { "x-vcard", &AnyTypeBodyPartFormatter::create }, - { "vcard", &AnyTypeBodyPartFormatter::create }, - { "rtf", &AnyTypeBodyPartFormatter::create }, - { "*", &TextPlainBodyPartFormatter::create }, + { "html", &TextHtmlBodyPartFormatter::create }, + //{ "enriched", &TextEnrichedBodyPartFormatter::create }, + { "x-vcard", &AnyTypeBodyPartFormatter::create }, + { "vcard", &AnyTypeBodyPartFormatter::create }, + { "rtf", &AnyTypeBodyPartFormatter::create }, + { "*", &TextPlainBodyPartFormatter::create }, }; static const SubtypeBuiltin multipartSubtypeBuiltins[] = { - { "mixed", &MultiPartMixedBodyPartFormatter::create }, - { "alternative", &MultiPartAlternativeBodyPartFormatter::create }, - //{ "digest", &MultiPartDigestFormatter::create }, - //{ "parallel", &MultiPartParallelFormatter::create }, - //{ "related", &MultiPartRelatedFormatter::create }, - { "signed", &MultiPartSignedBodyPartFormatter::create }, - { "encrypted", &MultiPartEncryptedBodyPartFormatter::create }, - //{ "report", &MultiPartReportFormatter::create }, + { "mixed", &MultiPartMixedBodyPartFormatter::create }, + { "alternative", &MultiPartAlternativeBodyPartFormatter::create }, + //{ "digest", &MultiPartDigestFormatter::create }, + //{ "parallel", &MultiPartParallelFormatter::create }, + //{ "related", &MultiPartRelatedFormatter::create }, + { "signed", &MultiPartSignedBodyPartFormatter::create }, + { "encrypted", &MultiPartEncryptedBodyPartFormatter::create }, + //{ "report", &MultiPartReportFormatter::create }, }; static const SubtypeBuiltin messageSubtypeBuiltins[] = { - { "rfc822", &MessageRfc822BodyPartFormatter::create }, + { "rfc822", &MessageRfc822BodyPartFormatter::create }, }; static const SubtypeBuiltin imageSubtypeBuiltins[] = { - { "*", &ImageTypeBodyPartFormatter::create }, + { "*", &ImageTypeBodyPartFormatter::create }, }; static const SubtypeBuiltin anySubtypeBuiltins[] = { - { "*", &AnyTypeBodyPartFormatter::create }, + { "*", &AnyTypeBodyPartFormatter::create }, }; #ifdef DIM @@ -189,134 +189,134 @@ #define DIM(x) sizeof(x) / sizeof(*x) static const struct { - const char * type; - const SubtypeBuiltin * subtypes; - unsigned int num_subtypes; + const char * type; + const SubtypeBuiltin * subtypes; + unsigned int num_subtypes; } builtins[] = { - { "application", applicationSubtypeBuiltins, DIM(applicationSubtypeBuiltins) }, - { "text", textSubtypeBuiltins, DIM(textSubtypeBuiltins) }, - { "multipart", multipartSubtypeBuiltins, DIM(multipartSubtypeBuiltins) }, - { "message", messageSubtypeBuiltins, DIM(messageSubtypeBuiltins) }, - { "image", imageSubtypeBuiltins, DIM(imageSubtypeBuiltins) }, - //{ "audio", audioSubtypeBuiltins, DIM(audioSubtypeBuiltins) }, - //{ "model", modelSubtypeBuiltins, DIM(modelSubtypeBuiltins) }, - //{ "video", videoSubtypeBuiltins, DIM(videoSubtypeBuiltins) }, - { "*", anySubtypeBuiltins, DIM(anySubtypeBuiltins) }, +{ "application", applicationSubtypeBuiltins, DIM(applicationSubtypeBuiltins) }, +{ "text", textSubtypeBuiltins, DIM(textSubtypeBuiltins) }, +{ "multipart", multipartSubtypeBuiltins, DIM(multipartSubtypeBuiltins) }, +{ "message", messageSubtypeBuiltins, DIM(messageSubtypeBuiltins) }, +{ "image", imageSubtypeBuiltins, DIM(imageSubtypeBuiltins) }, +//{ "audio", audioSubtypeBuiltins, DIM(audioSubtypeBuiltins) }, +//{ "model", modelSubtypeBuiltins, DIM(modelSubtypeBuiltins) }, +//{ "video", videoSubtypeBuiltins, DIM(videoSubtypeBuiltins) }, +{ "*", anySubtypeBuiltins, DIM(anySubtypeBuiltins) }, }; #undef DIM static const BodyPartFormatter * createForText( const char * subtype ) { - if ( subtype && *subtype ) - switch ( subtype[0] ) { - case 'h': - case 'H': - if ( kasciistricmp( subtype, "html" ) == 0 ) - return TextHtmlBodyPartFormatter::create(); - break; - case 'r': - case 'R': - if ( kasciistricmp( subtype, "rtf" ) == 0 ) - return AnyTypeBodyPartFormatter::create(); - break; - case 'x': - case 'X': - case 'v': - case 'V': - if ( kasciistricmp( subtype, "x-vcard" ) == 0 || - kasciistricmp( subtype, "vcard" ) == 0 ) - return AnyTypeBodyPartFormatter::create(); - break; - } + if ( subtype && *subtype ) + switch ( subtype[0] ) { + case 'h': + case 'H': + if ( kasciistricmp( subtype, "html" ) == 0 ) + return TextHtmlBodyPartFormatter::create(); + break; + case 'r': + case 'R': + if ( kasciistricmp( subtype, "rtf" ) == 0 ) + return AnyTypeBodyPartFormatter::create(); + break; + case 'x': + case 'X': + case 'v': + case 'V': + if ( kasciistricmp( subtype, "x-vcard" ) == 0 || + kasciistricmp( subtype, "vcard" ) == 0 ) + return AnyTypeBodyPartFormatter::create(); + break; + } - return TextPlainBodyPartFormatter::create(); + return TextPlainBodyPartFormatter::create(); } static const BodyPartFormatter * createForImage( const char * ) { - return ImageTypeBodyPartFormatter::create(); + return ImageTypeBodyPartFormatter::create(); } static const BodyPartFormatter * createForMessage( const char * subtype ) { - if ( kasciistricmp( subtype, "rfc822" ) == 0 ) - return MessageRfc822BodyPartFormatter::create(); - return AnyTypeBodyPartFormatter::create(); + if ( kasciistricmp( subtype, "rfc822" ) == 0 ) + return MessageRfc822BodyPartFormatter::create(); + return AnyTypeBodyPartFormatter::create(); } static const BodyPartFormatter * createForMultiPart( const char * subtype ) { - if ( subtype && *subtype ) - switch ( subtype[0] ) { - case 'a': - case 'A': - if ( kasciistricmp( subtype, "alternative" ) == 0 ) - return MultiPartAlternativeBodyPartFormatter::create(); - break; - case 'e': - case 'E': - if ( kasciistricmp( subtype, "encrypted" ) == 0 ) - return MultiPartEncryptedBodyPartFormatter::create(); - break; - case 's': - case 'S': - if ( kasciistricmp( subtype, "signed" ) == 0 ) - return MultiPartSignedBodyPartFormatter::create(); - break; - } + if ( subtype && *subtype ) + switch ( subtype[0] ) { + case 'a': + case 'A': + if ( kasciistricmp( subtype, "alternative" ) == 0 ) + return MultiPartAlternativeBodyPartFormatter::create(); + break; + case 'e': + case 'E': + if ( kasciistricmp( subtype, "encrypted" ) == 0 ) + return MultiPartEncryptedBodyPartFormatter::create(); + break; + case 's': + case 'S': + if ( kasciistricmp( subtype, "signed" ) == 0 ) + return MultiPartSignedBodyPartFormatter::create(); + break; + } - return MultiPartMixedBodyPartFormatter::create(); + return MultiPartMixedBodyPartFormatter::create(); } static const BodyPartFormatter * createForApplication( const char * subtype ) { - if ( subtype && *subtype ) - switch ( subtype[0] ) { - case 'p': - case 'P': - if ( kasciistricmp( subtype, "pgp" ) == 0 ) - return ApplicationPgpBodyPartFormatter::create(); - // fall through - case 'x': - case 'X': - if ( kasciistricmp( subtype, "pkcs7-mime" ) == 0 || - kasciistricmp( subtype, "x-pkcs7-mime" ) == 0 ) - return ApplicationPkcs7MimeBodyPartFormatter::create(); - break; - case 'v': - case 'V': - if ( kasciistricmp( subtype, "vnd.de.bund.bsi.chiasmus-text") == 0) - return ApplicationChiasmusTextBodyPartFormatter::create(); - break; - } + if ( subtype && *subtype ) + switch ( subtype[0] ) { + case 'p': + case 'P': + if ( kasciistricmp( subtype, "pgp" ) == 0 ) + return ApplicationPgpBodyPartFormatter::create(); + // fall through + case 'x': + case 'X': + if ( kasciistricmp( subtype, "pkcs7-mime" ) == 0 || + kasciistricmp( subtype, "x-pkcs7-mime" ) == 0 ) + return ApplicationPkcs7MimeBodyPartFormatter::create(); + break; + case 'v': + case 'V': + if ( kasciistricmp( subtype, "vnd.de.bund.bsi.chiasmus-text") == 0) + return ApplicationChiasmusTextBodyPartFormatter::create(); + break; + } - return AnyTypeBodyPartFormatter::create(); + return AnyTypeBodyPartFormatter::create(); } // OK, replace this with a factory with plugin support later on... const BodyPartFormatter * BodyPartFormatter::createFor( const char * type, const char * subtype ) { - if ( type && *type ) - switch ( type[0] ) { - case 'a': // application - case 'A': - if ( kasciistricmp( type, "application" ) == 0 ) - return createForApplication( subtype ); - break; - case 'i': // image - case 'I': - if ( kasciistricmp( type, "image" ) == 0 ) - return createForImage( subtype ); - break; - case 'm': // multipart / message - case 'M': - if ( kasciistricmp( type, "multipart" ) == 0 ) - return createForMultiPart( subtype ); - else if ( kasciistricmp( type, "message" ) == 0 ) - return createForMessage( subtype ); - break; - case 't': // text - case 'T': - if ( kasciistricmp( type, "text" ) == 0 ) - return createForText( subtype ); - break; - } + if ( type && *type ) + switch ( type[0] ) { + case 'a': // application + case 'A': + if ( kasciistricmp( type, "application" ) == 0 ) + return createForApplication( subtype ); + break; + case 'i': // image + case 'I': + if ( kasciistricmp( type, "image" ) == 0 ) + return createForImage( subtype ); + break; + case 'm': // multipart / message + case 'M': + if ( kasciistricmp( type, "multipart" ) == 0 ) + return createForMultiPart( subtype ); + else if ( kasciistricmp( type, "message" ) == 0 ) + return createForMessage( subtype ); + break; + case 't': // text + case 'T': + if ( kasciistricmp( type, "text" ) == 0 ) + return createForText( subtype ); + break; + } - return AnyTypeBodyPartFormatter::create(); + return AnyTypeBodyPartFormatter::create(); } diff -Nru kdepim-4.12.97/messageviewer/viewer/bodypartformatterfactory.cpp kdepim-4.13.0/messageviewer/viewer/bodypartformatterfactory.cpp --- kdepim-4.12.97/messageviewer/viewer/bodypartformatterfactory.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/bodypartformatterfactory.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -55,141 +55,141 @@ namespace { - DEFINE_PLUGIN_LOADER( BodyPartFormatterPluginLoader, - Interface::BodyPartFormatterPlugin, - "create_bodypart_formatter_plugin", - "messageviewer/plugins/bodypartformatter/*.desktop" ) +DEFINE_PLUGIN_LOADER( BodyPartFormatterPluginLoader, + Interface::BodyPartFormatterPlugin, + "create_bodypart_formatter_plugin", + "messageviewer/plugins/bodypartformatter/*.desktop" ) } BodyPartFormatterFactory * BodyPartFormatterFactory::mSelf = 0; const BodyPartFormatterFactory * BodyPartFormatterFactory::instance() { - if ( !mSelf ) - mSelf = new BodyPartFormatterFactory(); - return mSelf; + if ( !mSelf ) + mSelf = new BodyPartFormatterFactory(); + return mSelf; } BodyPartFormatterFactory::BodyPartFormatterFactory() { - mSelf = this; + mSelf = this; } BodyPartFormatterFactory::~BodyPartFormatterFactory() { - mSelf = 0; + mSelf = 0; } static TypeRegistry * all = 0; static void insertBodyPartFormatter( const char * type, const char * subtype, const Interface::BodyPartFormatter * formatter ) { - if ( !type || !*type || !subtype || !*subtype || !formatter || !all ) - return; + if ( !type || !*type || !subtype || !*subtype || !formatter || !all ) + return; - TypeRegistry::iterator type_it = all->find( type ); - if ( type_it == all->end() ) { - //kDebug() << "BodyPartFormatterFactory: instantiating new Subtype Registry for \"" - // << type << "\""; - type_it = all->insert( std::make_pair( type, SubtypeRegistry() ) ).first; - assert( type_it != all->end() ); - } - - SubtypeRegistry & subtype_reg = type_it->second; - SubtypeRegistry::iterator subtype_it = subtype_reg.find( subtype ); - if ( subtype_it != subtype_reg.end() ) { - kDebug() << "BodyPartFormatterFactory: overwriting previously registered formatter for \"" - << type << "/" << subtype << "\""; - subtype_reg.erase( subtype_it ); subtype_it = subtype_reg.end(); - } + TypeRegistry::iterator type_it = all->find( type ); + if ( type_it == all->end() ) { + //kDebug() << "BodyPartFormatterFactory: instantiating new Subtype Registry for \"" + // << type << "\""; + type_it = all->insert( std::make_pair( type, SubtypeRegistry() ) ).first; + assert( type_it != all->end() ); + } + + SubtypeRegistry & subtype_reg = type_it->second; + SubtypeRegistry::iterator subtype_it = subtype_reg.find( subtype ); + if ( subtype_it != subtype_reg.end() ) { + kDebug() << "BodyPartFormatterFactory: overwriting previously registered formatter for \"" + << type << "/" << subtype << "\""; + subtype_reg.erase( subtype_it ); subtype_it = subtype_reg.end(); + } - subtype_reg.insert( std::make_pair( subtype, formatter ) ); + subtype_reg.insert( std::make_pair( subtype, formatter ) ); } static void loadPlugins() { - const BodyPartFormatterPluginLoader * pl = BodyPartFormatterPluginLoader::instance(); - if ( !pl ) { - kWarning() << "BodyPartFormatterFactory: cannot instantiate plugin loader!"; - return; - } - const QStringList types = pl->types(); - //kDebug() << "BodyPartFormatterFactory: found" << types.size() << "plugins."; - for ( QStringList::const_iterator it = types.begin() ; it != types.end() ; ++it ) { - const Interface::BodyPartFormatterPlugin * plugin = pl->createForName( *it ); - if ( !plugin ) { - kWarning() << "BodyPartFormatterFactory: plugin" << *it << "is not valid!"; - continue; - } - const Interface::BodyPartFormatter * bfp; - for ( int i = 0 ; (bfp = plugin->bodyPartFormatter( i )) ; ++i ) { - const char * type = plugin->type( i ); - if ( !type || !*type ) { - kWarning() << "BodyPartFormatterFactory: plugin" << *it - << "returned empty type specification for index" - << i; - break; - } - const char * subtype = plugin->subtype( i ); - if ( !subtype || !*subtype ) { - kWarning() << "BodyPartFormatterFactory: plugin" << *it - << "returned empty subtype specification for index" - << i; - break; - } - insertBodyPartFormatter( type, subtype, bfp ); - } - const Interface::BodyPartURLHandler * handler; - for ( int i = 0 ; (handler = plugin->urlHandler( i )) ; ++i ) - URLHandlerManager::instance()->registerHandler( handler ); - } + const BodyPartFormatterPluginLoader * pl = BodyPartFormatterPluginLoader::instance(); + if ( !pl ) { + kWarning() << "BodyPartFormatterFactory: cannot instantiate plugin loader!"; + return; + } + const QStringList types = pl->types(); + //kDebug() << "BodyPartFormatterFactory: found" << types.size() << "plugins."; + for ( QStringList::const_iterator it = types.begin() ; it != types.end() ; ++it ) { + const Interface::BodyPartFormatterPlugin * plugin = pl->createForName( *it ); + if ( !plugin ) { + kWarning() << "BodyPartFormatterFactory: plugin" << *it << "is not valid!"; + continue; + } + const Interface::BodyPartFormatter * bfp; + for ( int i = 0 ; (bfp = plugin->bodyPartFormatter( i )) ; ++i ) { + const char * type = plugin->type( i ); + if ( !type || !*type ) { + kWarning() << "BodyPartFormatterFactory: plugin" << *it + << "returned empty type specification for index" + << i; + break; + } + const char * subtype = plugin->subtype( i ); + if ( !subtype || !*subtype ) { + kWarning() << "BodyPartFormatterFactory: plugin" << *it + << "returned empty subtype specification for index" + << i; + break; + } + insertBodyPartFormatter( type, subtype, bfp ); + } + const Interface::BodyPartURLHandler * handler; + for ( int i = 0 ; (handler = plugin->urlHandler( i )) ; ++i ) + URLHandlerManager::instance()->registerHandler( handler ); + } } static void setup() { - if ( !all ) { - all = new TypeRegistry(); - messageviewer_create_builtin_bodypart_formatters( all ); - loadPlugins(); - } + if ( !all ) { + all = new TypeRegistry(); + messageviewer_create_builtin_bodypart_formatters( all ); + loadPlugins(); + } } const Interface::BodyPartFormatter * BodyPartFormatterFactory::createFor( const char * type, const char * subtype ) const { - if ( !type || !*type ) - type = "*"; //krazy:exclude=doublequote_chars - if ( !subtype || !*subtype ) - subtype = "*"; //krazy:exclude=doublequote_chars - - setup(); - assert( all ); - - if ( all->empty() ) - return 0; - - TypeRegistry::const_iterator type_it = all->find( type ); - if ( type_it == all->end() ) - type_it = all->find( "*" ); - if ( type_it == all->end() ) - return 0; - - const SubtypeRegistry & subtype_reg = type_it->second; - if ( subtype_reg.empty() ) - return 0; - - SubtypeRegistry::const_iterator subtype_it = subtype_reg.find( subtype ); - if ( subtype_it == subtype_reg.end() ) - subtype_it = subtype_reg.find( "*" ); - if ( subtype_it == subtype_reg.end() ) - return 0; - - if ( !(*subtype_it).second ) { - kWarning() << "BodyPartFormatterFactory: a null bodypart formatter sneaked in for \"" - << type << "/" << subtype << "\"!"; - } + if ( !type || !*type ) + type = "*"; //krazy:exclude=doublequote_chars + if ( !subtype || !*subtype ) + subtype = "*"; //krazy:exclude=doublequote_chars + + setup(); + assert( all ); + + if ( all->empty() ) + return 0; + + TypeRegistry::const_iterator type_it = all->find( type ); + if ( type_it == all->end() ) + type_it = all->find( "*" ); + if ( type_it == all->end() ) + return 0; + + const SubtypeRegistry & subtype_reg = type_it->second; + if ( subtype_reg.empty() ) + return 0; + + SubtypeRegistry::const_iterator subtype_it = subtype_reg.find( subtype ); + if ( subtype_it == subtype_reg.end() ) + subtype_it = subtype_reg.find( "*" ); + if ( subtype_it == subtype_reg.end() ) + return 0; + + if ( !(*subtype_it).second ) { + kWarning() << "BodyPartFormatterFactory: a null bodypart formatter sneaked in for \"" + << type << "/" << subtype << "\"!"; + } - return (*subtype_it).second; + return (*subtype_it).second; } const Interface::BodyPartFormatter * BodyPartFormatterFactory::createFor( const QString & type, const QString & subtype ) const { - return createFor( type.toLatin1(), subtype.toLatin1() ); + return createFor( type.toLatin1(), subtype.toLatin1() ); } const Interface::BodyPartFormatter * BodyPartFormatterFactory::createFor( const QByteArray & type, const QByteArray & subtype ) const { - return createFor( type.data(), subtype.data() ); + return createFor( type.data(), subtype.data() ); } diff -Nru kdepim-4.12.97/messageviewer/viewer/bodypartformatterfactory.h kdepim-4.13.0/messageviewer/viewer/bodypartformatterfactory.h --- kdepim-4.12.97/messageviewer/viewer/bodypartformatterfactory.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/bodypartformatterfactory.h 2014-04-10 07:40:20.000000000 +0000 @@ -41,32 +41,32 @@ namespace MessageViewer { namespace Interface { - class BodyPartFormatter; +class BodyPartFormatter; } class BodyPartFormatterFactory { - class gcc_shut_up; - friend class BodyPartFormatterFactory::gcc_shut_up; + class gcc_shut_up; + friend class BodyPartFormatterFactory::gcc_shut_up; public: - ~BodyPartFormatterFactory(); + ~BodyPartFormatterFactory(); - static const BodyPartFormatterFactory * instance(); + static const BodyPartFormatterFactory * instance(); - const Interface::BodyPartFormatter * createFor( const char * type, const char * subtype ) const; - const Interface::BodyPartFormatter * createFor( const QString & type, const QString & subtype ) const; - const Interface::BodyPartFormatter * createFor( const QByteArray & type, const QByteArray & subtype ) const; + const Interface::BodyPartFormatter * createFor( const char * type, const char * subtype ) const; + const Interface::BodyPartFormatter * createFor( const QString & type, const QString & subtype ) const; + const Interface::BodyPartFormatter * createFor( const QByteArray & type, const QByteArray & subtype ) const; - // - // Only boring stuff below: - // + // + // Only boring stuff below: + // private: - BodyPartFormatterFactory(); - static BodyPartFormatterFactory * mSelf; + BodyPartFormatterFactory(); + static BodyPartFormatterFactory * mSelf; private: - // disabled - const BodyPartFormatterFactory & operator=( const BodyPartFormatterFactory & ); - BodyPartFormatterFactory( const BodyPartFormatterFactory & ); + // disabled + const BodyPartFormatterFactory & operator=( const BodyPartFormatterFactory & ); + BodyPartFormatterFactory( const BodyPartFormatterFactory & ); }; } diff -Nru kdepim-4.12.97/messageviewer/viewer/bodypartformatter.h kdepim-4.13.0/messageviewer/viewer/bodypartformatter.h --- kdepim-4.12.97/messageviewer/viewer/bodypartformatter.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/bodypartformatter.h 2014-04-10 07:40:20.000000000 +0000 @@ -34,28 +34,28 @@ namespace KMime { - class Content; +class Content; } namespace MessageViewer { - class ObjectTreeParser; - class ProcessResult; +class ObjectTreeParser; +class ProcessResult; } namespace MessageViewer { class BodyPartFormatter { - const BodyPartFormatter & operator=( const BodyPartFormatter & ); - BodyPartFormatter( const BodyPartFormatter & ); + const BodyPartFormatter & operator=( const BodyPartFormatter & ); + BodyPartFormatter( const BodyPartFormatter & ); protected: - BodyPartFormatter() {} + BodyPartFormatter() {} public: - virtual ~BodyPartFormatter() {} + virtual ~BodyPartFormatter() {} - virtual bool process( ObjectTreeParser *, KMime::Content *, ProcessResult & ) const = 0; + virtual bool process( ObjectTreeParser *, KMime::Content *, ProcessResult & ) const = 0; - static const BodyPartFormatter * createFor( const char * type, const char * subtype ); + static const BodyPartFormatter * createFor( const char * type, const char * subtype ); }; } diff -Nru kdepim-4.12.97/messageviewer/viewer/chiasmuskeyselector.cpp kdepim-4.13.0/messageviewer/viewer/chiasmuskeyselector.cpp --- kdepim-4.12.97/messageviewer/viewer/chiasmuskeyselector.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/chiasmuskeyselector.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -14,59 +14,59 @@ ChiasmusKeySelector::ChiasmusKeySelector( QWidget* parent, const QString& caption, const QStringList& keys, const QString& currentKey, const QString& lastOptions ) - : KDialog( parent ) + : KDialog( parent ) { - setCaption( caption ); - setButtons( Ok | Cancel ); - QWidget *page = new QWidget( this ); - setMainWidget(page); - - QVBoxLayout *layout = new QVBoxLayout(page); - layout->setSpacing(KDialog::spacingHint()); - - mLabel = new QLabel( i18n( "Please select the Chiasmus key file to use:" ), page ); - layout->addWidget( mLabel ); - - mListBox = new KListWidget( page ); - mListBox->addItems( keys ); - const int current = keys.indexOf( currentKey ); - mListBox->setCurrentRow( qMax( 0, current ) ); - mListBox->scrollToItem( mListBox->item( qMax( 0, current ) ) ); - layout->addWidget( mListBox, 1 ); - - QLabel* optionLabel = new QLabel( i18n( "Additional arguments for chiasmus:" ), page ); - layout->addWidget( optionLabel ); - - mOptions = new KLineEdit( lastOptions, page ); - optionLabel->setBuddy( mOptions ); - layout->addWidget( mOptions ); + setCaption( caption ); + setButtons( Ok | Cancel ); + QWidget *page = new QWidget( this ); + setMainWidget(page); + + QVBoxLayout *layout = new QVBoxLayout(page); + layout->setSpacing(KDialog::spacingHint()); + + mLabel = new QLabel( i18n( "Please select the Chiasmus key file to use:" ), page ); + layout->addWidget( mLabel ); + + mListBox = new KListWidget( page ); + mListBox->addItems( keys ); + const int current = keys.indexOf( currentKey ); + mListBox->setCurrentRow( qMax( 0, current ) ); + mListBox->scrollToItem( mListBox->item( qMax( 0, current ) ) ); + layout->addWidget( mListBox, 1 ); + + QLabel* optionLabel = new QLabel( i18n( "Additional arguments for chiasmus:" ), page ); + layout->addWidget( optionLabel ); + + mOptions = new KLineEdit( lastOptions, page ); + optionLabel->setBuddy( mOptions ); + layout->addWidget( mOptions ); - layout->addStretch(); + layout->addStretch(); - connect( mListBox, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(accept()) ); - connect( mListBox, SIGNAL(itemSelectionChanged()), this, SLOT(slotItemSelectionChanged()) ); + connect( mListBox, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(accept()) ); + connect( mListBox, SIGNAL(itemSelectionChanged()), this, SLOT(slotItemSelectionChanged()) ); - slotItemSelectionChanged(); - mListBox->setFocus(); + slotItemSelectionChanged(); + mListBox->setFocus(); } void ChiasmusKeySelector::slotItemSelectionChanged() { - button( Ok )->setEnabled( !mListBox->selectedItems().isEmpty() ); + button( Ok )->setEnabled( !mListBox->selectedItems().isEmpty() ); } QString ChiasmusKeySelector::key() const { - if (mListBox->selectedItems().isEmpty()) { - return QString(); - } - else - return mListBox->currentItem()->text(); + if (mListBox->selectedItems().isEmpty()) { + return QString(); + } + else + return mListBox->currentItem()->text(); } QString ChiasmusKeySelector::options() const { - return mOptions->text(); + return mOptions->text(); } } diff -Nru kdepim-4.12.97/messageviewer/viewer/chiasmuskeyselector.h kdepim-4.13.0/messageviewer/viewer/chiasmuskeyselector.h --- kdepim-4.12.97/messageviewer/viewer/chiasmuskeyselector.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/chiasmuskeyselector.h 2014-04-10 07:40:20.000000000 +0000 @@ -12,23 +12,23 @@ class MESSAGEVIEWER_EXPORT ChiasmusKeySelector : public KDialog { - Q_OBJECT + Q_OBJECT public: - ChiasmusKeySelector( QWidget* parent, const QString& caption, - const QStringList& keys, const QString& currentKey, - const QString& lastOptions ); + ChiasmusKeySelector( QWidget* parent, const QString& caption, + const QStringList& keys, const QString& currentKey, + const QString& lastOptions ); - QString key() const; - QString options() const; + QString key() const; + QString options() const; private Q_SLOTS: - void slotItemSelectionChanged(); + void slotItemSelectionChanged(); private: - QLabel* mLabel; - KListWidget* mListBox; - KLineEdit* mOptions; + QLabel* mLabel; + KListWidget* mListBox; + KLineEdit* mOptions; }; } diff -Nru kdepim-4.12.97/messageviewer/viewer/csshelperbase.cpp kdepim-4.13.0/messageviewer/viewer/csshelperbase.cpp --- kdepim-4.12.97/messageviewer/viewer/csshelperbase.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/csshelperbase.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -42,37 +42,37 @@ namespace MessageViewer { - namespace { - // some QColor manipulators that hide the ugly QColor API w.r.t. HSV: - inline QColor darker( const QColor & c ) { - int h, s, v; - c.getHsv( &h, &s, &v ); - return QColor::fromHsv( h, s, v*4/5 ); - } +namespace { +// some QColor manipulators that hide the ugly QColor API w.r.t. HSV: +inline QColor darker( const QColor & c ) { + int h, s, v; + c.getHsv( &h, &s, &v ); + return QColor::fromHsv( h, s, v*4/5 ); +} - inline QColor desaturate( const QColor & c ) { - int h, s, v; - c.getHsv( &h, &s, &v ); - return QColor::fromHsv( h, s/8, v ); - } +inline QColor desaturate( const QColor & c ) { + int h, s, v; + c.getHsv( &h, &s, &v ); + return QColor::fromHsv( h, s/8, v ); +} - inline QColor fixValue( const QColor & c, int newV ) { - int h, s, v; - c.getHsv( &h, &s, &v ); - return QColor::fromHsv( h, s, newV ); - } +inline QColor fixValue( const QColor & c, int newV ) { + int h, s, v; + c.getHsv( &h, &s, &v ); + return QColor::fromHsv( h, s, newV ); +} - inline int getValueOf( const QColor & c ) { - int h, s, v; - c.getHsv( &h, &s, &v ); - return v; - } - } +inline int getValueOf( const QColor & c ) { + int h, s, v; + c.getHsv( &h, &s, &v ); + return v; +} +} - CSSHelperBase::CSSHelperBase( const QPaintDevice *pd ) : +CSSHelperBase::CSSHelperBase( const QPaintDevice *pd ) : mShrinkQuotes( false ), mPaintDevice( pd ) - { +{ // initialize with defaults - should match the corresponding application defaults mForegroundColor = QApplication::palette().color( QPalette::Text ); mLinkColor = KColorScheme( QPalette::Active, KColorScheme::View ).foreground( KColorScheme::LinkText ).color(); @@ -87,13 +87,13 @@ cPgpErrH = Qt::red; if(MessageCore::GlobalSettings::self()->useDefaultColors()) { - for ( int i = 0 ; i < 3 ; ++i ) { - mQuoteColor[i] = QColor( 0x00, 0x80 - i * 0x10, 0x00 ); // shades of green - } + for ( int i = 0 ; i < 3 ; ++i ) { + mQuoteColor[i] = QColor( 0x00, 0x80 - i * 0x10, 0x00 ); // shades of green + } } else { - mQuoteColor[0] = MessageCore::GlobalSettings::self()->quotedText1(); - mQuoteColor[1] = MessageCore::GlobalSettings::self()->quotedText2(); - mQuoteColor[2] = MessageCore::GlobalSettings::self()->quotedText3(); + mQuoteColor[0] = MessageCore::GlobalSettings::self()->quotedText1(); + mQuoteColor[1] = MessageCore::GlobalSettings::self()->quotedText2(); + mQuoteColor[2] = MessageCore::GlobalSettings::self()->quotedText3(); } mRecycleQuoteColors = false; @@ -104,14 +104,14 @@ mFixedFont = mFixedPrintFont = defaultFixedFont; defaultFont.setItalic( true ); for ( int i = 0 ; i < 3 ; ++i ) - mQuoteFont[i] = defaultFont; + mQuoteFont[i] = defaultFont; mBackingPixmapOn = false; recalculatePGPColors(); - } +} - void CSSHelperBase::recalculatePGPColors() { +void CSSHelperBase::recalculatePGPColors() { // determine the frame and body color for PGP messages from the header color // if the header color equals the background color then the other colors are // also set to the background color (-> old style PGP message viewing) @@ -126,575 +126,575 @@ const int vBG = getValueOf( mBackgroundColor ); const bool lightBG = vBG >= 128; if ( cPgpOk1H == mBackgroundColor ) { - cPgpOk1F = mBackgroundColor; - cPgpOk1B = mBackgroundColor; + cPgpOk1F = mBackgroundColor; + cPgpOk1B = mBackgroundColor; } else { - cPgpOk1F= darker( cPgpOk1H ); - cPgpOk1B = lightBG ? desaturate( cPgpOk1H ) : fixValue( cPgpOk1H, vBG ); + cPgpOk1F= darker( cPgpOk1H ); + cPgpOk1B = lightBG ? desaturate( cPgpOk1H ) : fixValue( cPgpOk1H, vBG ); } if ( cPgpOk0H == mBackgroundColor ) { - cPgpOk0F = mBackgroundColor; - cPgpOk0B = mBackgroundColor; + cPgpOk0F = mBackgroundColor; + cPgpOk0B = mBackgroundColor; } else { - cPgpOk0F = darker( cPgpOk0H ); - cPgpOk0B = lightBG ? desaturate( cPgpOk0H ) : fixValue( cPgpOk0H, vBG ); + cPgpOk0F = darker( cPgpOk0H ); + cPgpOk0B = lightBG ? desaturate( cPgpOk0H ) : fixValue( cPgpOk0H, vBG ); } if ( cPgpWarnH == mBackgroundColor ) { - cPgpWarnF = mBackgroundColor; - cPgpWarnB = mBackgroundColor; + cPgpWarnF = mBackgroundColor; + cPgpWarnB = mBackgroundColor; } else { - cPgpWarnF = darker( cPgpWarnH ); - cPgpWarnB = lightBG ? desaturate( cPgpWarnH ) : fixValue( cPgpWarnH, vBG ); + cPgpWarnF = darker( cPgpWarnH ); + cPgpWarnB = lightBG ? desaturate( cPgpWarnH ) : fixValue( cPgpWarnH, vBG ); } if ( cPgpErrH == mBackgroundColor ) { - cPgpErrF = mBackgroundColor; - cPgpErrB = mBackgroundColor; + cPgpErrF = mBackgroundColor; + cPgpErrB = mBackgroundColor; } else { - cPgpErrF = darker( cPgpErrH ); - cPgpErrB = lightBG ? desaturate( cPgpErrH ) : fixValue( cPgpErrH, vBG ); + cPgpErrF = darker( cPgpErrH ); + cPgpErrB = lightBG ? desaturate( cPgpErrH ) : fixValue( cPgpErrH, vBG ); } if ( cPgpEncrH == mBackgroundColor ) { - cPgpEncrF = mBackgroundColor; - cPgpEncrB = mBackgroundColor; + cPgpEncrF = mBackgroundColor; + cPgpEncrB = mBackgroundColor; } else { - cPgpEncrF = darker( cPgpEncrH ); - cPgpEncrB = lightBG ? desaturate( cPgpEncrH ) : fixValue( cPgpEncrH, vBG ); + cPgpEncrF = darker( cPgpEncrH ); + cPgpEncrB = lightBG ? desaturate( cPgpEncrH ) : fixValue( cPgpEncrH, vBG ); } - } +} - QString CSSHelperBase::cssDefinitions( bool fixed ) const { +QString CSSHelperBase::cssDefinitions( bool fixed ) const { return - commonCssDefinitions() - + - QLatin1String("@media screen {\n\n") - + - screenCssDefinitions( this, fixed ) - + - QLatin1String("}\n" - "@media print {\n\n") - + - printCssDefinitions( fixed ) - + - QLatin1String("\n"); - } + commonCssDefinitions() + + + QLatin1String("@media screen {\n\n") + + + screenCssDefinitions( this, fixed ) + + + QLatin1String("}\n" + "@media print {\n\n") + + + printCssDefinitions( fixed ) + + + QLatin1String("\n"); +} - QString CSSHelperBase::htmlHead( bool /*fixed*/ ) const { +QString CSSHelperBase::htmlHead( bool /*fixed*/ ) const { return - QLatin1String("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" - "<html><head><title>\n" - "\n"); - } + QLatin1String("\n" + "\n" + "\n"); +} - QString CSSHelperBase::quoteFontTag( int level ) const { +QString CSSHelperBase::quoteFontTag( int level ) const { if ( level < 0 ) - level = 0; + level = 0; static const int numQuoteLevels = sizeof mQuoteFont / sizeof *mQuoteFont; const int effectiveLevel = mRecycleQuoteColors - ? level % numQuoteLevels + 1 - : qMin( level + 1, numQuoteLevels ) ; + ? level % numQuoteLevels + 1 + : qMin( level + 1, numQuoteLevels ) ; if ( level >= numQuoteLevels ) - return QString::fromLatin1( "
" ).arg( effectiveLevel ); + return QString::fromLatin1( "
" ).arg( effectiveLevel ); else - return QString::fromLatin1( "
" ).arg( effectiveLevel ); - } + return QString::fromLatin1( "
" ).arg( effectiveLevel ); +} - QString CSSHelperBase::nonQuotedFontTag() const { +QString CSSHelperBase::nonQuotedFontTag() const { return QLatin1String("
"); - } +} - QFont CSSHelperBase::bodyFont( bool fixed, bool print ) const { - return fixed ? ( print ? mFixedPrintFont : mFixedFont ) - : ( print ? mPrintFont : mBodyFont ); - } +QFont CSSHelperBase::bodyFont( bool fixed, bool print ) const { + return fixed ? ( print ? mFixedPrintFont : mFixedFont ) + : ( print ? mPrintFont : mBodyFont ); +} - int CSSHelperBase::fontSize( bool fixed, bool print ) const { +int CSSHelperBase::fontSize( bool fixed, bool print ) const { return bodyFont( fixed, print ).pointSize(); - } +} - namespace { - int pointsToPixel( const QPaintDevice *pd, int pointSize ) { - return ( pointSize * pd->logicalDpiY() + 36 ) / 72 ; - } - } +namespace { +int pointsToPixel( const QPaintDevice *pd, int pointSize ) { + return ( pointSize * pd->logicalDpiY() + 36 ) / 72 ; +} +} - static const char * const quoteFontSizes[] = { "85", "80", "75" }; +static const char * const quoteFontSizes[] = { "85", "80", "75" }; - QString CSSHelperBase::printCssDefinitions( bool fixed ) const { +QString CSSHelperBase::printCssDefinitions( bool fixed ) const { const QString headerFont = QString::fromLatin1( " font-family: \"%1\" ! important;\n" - " font-size: %2pt ! important;\n" ) - .arg( mPrintFont.family() ) - .arg( mPrintFont.pointSize() ); + " font-size: %2pt ! important;\n" ) + .arg( mPrintFont.family() ) + .arg( mPrintFont.pointSize() ); const QPalette &pal = QApplication::palette(); const QFont printFont = bodyFont( fixed, true /* print */ ); QString quoteCSS; if ( printFont.italic() ) - quoteCSS += QLatin1String(" font-style: italic ! important;\n"); + quoteCSS += QLatin1String(" font-style: italic ! important;\n"); if ( printFont.bold() ) - quoteCSS += QLatin1String(" font-weight: bold ! important;\n"); + quoteCSS += QLatin1String(" font-weight: bold ! important;\n"); if ( !quoteCSS.isEmpty() ) - quoteCSS = QLatin1String("div.noquote {\n") + quoteCSS + QLatin1String("}\n\n"); + quoteCSS = QLatin1String("div.noquote {\n") + quoteCSS + QLatin1String("}\n\n"); return - QString::fromLatin1( "body {\n" - " font-family: \"%1\" ! important;\n" - " font-size: %2pt ! important;\n" - " color: #000000 ! important;\n" - " background-color: #ffffff ! important\n" - "}\n\n" ) - .arg( printFont.family(), - QString::number( printFont.pointSize() ) ) - + - QString::fromLatin1( "tr.textAtmH,\n" - "tr.signInProgressH,\n" - "tr.rfc822H,\n" - "tr.encrH,\n" - "tr.signOkKeyOkH,\n" - "tr.signOkKeyBadH,\n" - "tr.signWarnH,\n" - "tr.signErrH,\n" - "div.header {\n" - "%1" - "}\n\n" - - "div.fancy.header > div {\n" - " background-color: %2 ! important;\n" - " color: %3 ! important;\n" - " padding: 4px ! important;\n" - " border: solid %3 1px ! important;\n" - " line-height: normal;\n" - "}\n\n" - - "div.fancy.header > div a[href] { color: %3 ! important; }\n\n" - - "div.fancy.header > table.outer{\n" - " background-color: %2 ! important;\n" - " color: %3 ! important;\n" - " border-bottom: solid %3 1px ! important;\n" - " border-left: solid %3 1px ! important;\n" - " border-right: solid %3 1px ! important;\n" - "}\n\n" - - "div.spamheader {\n" - " display:none ! important;\n" - "}\n\n" - - "div.htmlWarn {\n" - " border: 2px solid #ffffff ! important;\n" - " line-height: normal;\n" - "}\n\n" - - "div.senderpic{\n" - " font-size:0.8em ! important;\n" - " border:1px solid black ! important;\n" - " background-color:%2 ! important;\n" - "}\n\n" - - "div.senderstatus{\n" - " text-align:center ! important;\n" - "}\n\n" - - "div.noprint {\n" - " display:none ! important;\n" - "}\n\n" - ) - .arg( headerFont, - pal.color( QPalette::Background ).name(), - pal.color( QPalette::Foreground ).name() ) - + quoteCSS; - } + QString::fromLatin1( "body {\n" + " font-family: \"%1\" ! important;\n" + " font-size: %2pt ! important;\n" + " color: #000000 ! important;\n" + " background-color: #ffffff ! important\n" + "}\n\n" ) + .arg( printFont.family(), + QString::number( printFont.pointSize() ) ) + + + QString::fromLatin1( "tr.textAtmH,\n" + "tr.signInProgressH,\n" + "tr.rfc822H,\n" + "tr.encrH,\n" + "tr.signOkKeyOkH,\n" + "tr.signOkKeyBadH,\n" + "tr.signWarnH,\n" + "tr.signErrH,\n" + "div.header {\n" + "%1" + "}\n\n" + + "div.fancy.header > div {\n" + " background-color: %2 ! important;\n" + " color: %3 ! important;\n" + " padding: 4px ! important;\n" + " border: solid %3 1px ! important;\n" + " line-height: normal;\n" + "}\n\n" + + "div.fancy.header > div a[href] { color: %3 ! important; }\n\n" + + "div.fancy.header > table.outer{\n" + " background-color: %2 ! important;\n" + " color: %3 ! important;\n" + " border-bottom: solid %3 1px ! important;\n" + " border-left: solid %3 1px ! important;\n" + " border-right: solid %3 1px ! important;\n" + "}\n\n" + + "div.spamheader {\n" + " display:none ! important;\n" + "}\n\n" + + "div.htmlWarn {\n" + " border: 2px solid #ffffff ! important;\n" + " line-height: normal;\n" + "}\n\n" + + "div.senderpic{\n" + " font-size:0.8em ! important;\n" + " border:1px solid black ! important;\n" + " background-color:%2 ! important;\n" + "}\n\n" + + "div.senderstatus{\n" + " text-align:center ! important;\n" + "}\n\n" + + "div.noprint {\n" + " display:none ! important;\n" + "}\n\n" + ) + .arg( headerFont, + pal.color( QPalette::Background ).name(), + pal.color( QPalette::Foreground ).name() ) + + quoteCSS; +} - QString CSSHelperBase::screenCssDefinitions( const CSSHelperBase * helper, bool fixed ) const { +QString CSSHelperBase::screenCssDefinitions( const CSSHelperBase * helper, bool fixed ) const { const QString fgColor = mForegroundColor.name(); const QString bgColor = mBackgroundColor.name(); const QString linkColor = mLinkColor.name(); const QString headerFont = QString::fromLatin1(" font-family: \"%1\" ! important;\n" - " font-size: %2px ! important;\n") - .arg( mBodyFont.family() ) - .arg( pointsToPixel( helper->mPaintDevice, mBodyFont.pointSize() ) ); + " font-size: %2px ! important;\n") + .arg( mBodyFont.family() ) + .arg( pointsToPixel( helper->mPaintDevice, mBodyFont.pointSize() ) ); const QString background = ( mBackingPixmapOn - ? QString::fromLatin1( " background-image:url(file:///%1) ! important;\n" ) - .arg( mBackingPixmapStr ) - : QString::fromLatin1( " background-color: %1 ! important;\n" ) - .arg( bgColor ) ); + ? QString::fromLatin1( " background-image:url(file:///%1) ! important;\n" ) + .arg( mBackingPixmapStr ) + : QString::fromLatin1( " background-color: %1 ! important;\n" ) + .arg( bgColor ) ); const QString bodyFontSize = QString::number( pointsToPixel( helper->mPaintDevice, fontSize( fixed ) ) ) + QLatin1String("px"); const QPalette & pal = QApplication::palette(); QString quoteCSS; if ( bodyFont( fixed ).italic() ) - quoteCSS += QLatin1String(" font-style: italic ! important;\n"); + quoteCSS += QLatin1String(" font-style: italic ! important;\n"); if ( bodyFont( fixed ).bold() ) - quoteCSS += QLatin1String(" font-weight: bold ! important;\n"); + quoteCSS += QLatin1String(" font-weight: bold ! important;\n"); if ( !quoteCSS.isEmpty() ) - quoteCSS = QLatin1String("div.noquote {\n") + quoteCSS + QLatin1String("}\n\n"); + quoteCSS = QLatin1String("div.noquote {\n") + quoteCSS + QLatin1String("}\n\n"); // CSS definitions for quote levels 1-3 for ( int i = 0 ; i < 3 ; ++i ) { - quoteCSS += QString::fromLatin1( "div.quotelevel%1 {\n" - " color: %2 ! important;\n" ) - .arg( QString::number(i+1), mQuoteColor[i].name() ); - if ( mQuoteFont[i].italic() ) - quoteCSS += QLatin1String(" font-style: italic ! important;\n"); - if ( mQuoteFont[i].bold() ) - quoteCSS += QLatin1String(" font-weight: bold ! important;\n"); - if ( mShrinkQuotes ) - quoteCSS += QLatin1String(" font-size: ") + QString::fromLatin1( quoteFontSizes[i] ) - + QLatin1String("% ! important;\n"); - quoteCSS += QLatin1String("}\n\n"); + quoteCSS += QString::fromLatin1( "div.quotelevel%1 {\n" + " color: %2 ! important;\n" ) + .arg( QString::number(i+1), mQuoteColor[i].name() ); + if ( mQuoteFont[i].italic() ) + quoteCSS += QLatin1String(" font-style: italic ! important;\n"); + if ( mQuoteFont[i].bold() ) + quoteCSS += QLatin1String(" font-weight: bold ! important;\n"); + if ( mShrinkQuotes ) + quoteCSS += QLatin1String(" font-size: ") + QString::fromLatin1( quoteFontSizes[i] ) + + QLatin1String("% ! important;\n"); + quoteCSS += QLatin1String("}\n\n"); } // CSS definitions for quote levels 4+ for ( int i = 0 ; i < 3 ; ++i ) { - quoteCSS += QString::fromLatin1( "div.deepquotelevel%1 {\n" - " color: %2 ! important;\n" ) - .arg( QString::number(i+1), mQuoteColor[i].name() ); - if ( mQuoteFont[i].italic() ) - quoteCSS += QLatin1String(" font-style: italic ! important;\n"); - if ( mQuoteFont[i].bold() ) - quoteCSS += QLatin1String(" font-weight: bold ! important;\n"); - if ( mShrinkQuotes ) - quoteCSS += QLatin1String(" font-size: 70% ! important;\n"); - quoteCSS += QLatin1String("}\n\n"); + quoteCSS += QString::fromLatin1( "div.deepquotelevel%1 {\n" + " color: %2 ! important;\n" ) + .arg( QString::number(i+1), mQuoteColor[i].name() ); + if ( mQuoteFont[i].italic() ) + quoteCSS += QLatin1String(" font-style: italic ! important;\n"); + if ( mQuoteFont[i].bold() ) + quoteCSS += QLatin1String(" font-weight: bold ! important;\n"); + if ( mShrinkQuotes ) + quoteCSS += QLatin1String(" font-size: 70% ! important;\n"); + quoteCSS += QLatin1String("}\n\n"); } return - QString::fromLatin1( "body {\n" - " font-family: \"%1\" ! important;\n" - " font-size: %2 ! important;\n" - " color: %3 ! important;\n" - "%4" - "}\n\n" ) - .arg( bodyFont( fixed ).family(), - bodyFontSize, - fgColor, - background ) - + -/* This shouldn't be necessary because font properties are inherited - automatically and causes wrong font settings with QTextBrowser - because it doesn't understand the inherit statement - QString::fromLatin1( "table {\n" - " font-family: inherit ! important;\n" - " font-size: inherit ! important;\n" - " font-weight: inherit ! important;\n" - "}\n\n" ) - + - */ - QString::fromLatin1( "a {\n" - " color: %1 ! important;\n" - " text-decoration: none ! important;\n" - "}\n\n" - - "a.white {\n" - " color: white ! important;\n" - "}\n\n" - - "a.black {\n" - " color: black ! important;\n" - "}\n\n" - - "table.textAtm { background-color: %2 ! important; }\n\n" - - "tr.textAtmH {\n" - " background-color: %3 ! important;\n" - "%4" - "}\n\n" - - "tr.textAtmB {\n" - " background-color: %3 ! important;\n" - "}\n\n" - - "table.signInProgress,\n" - "table.rfc822 {\n" - " background-color: %3 ! important;\n" - "}\n\n" - - "tr.signInProgressH,\n" - "tr.rfc822H {\n" - "%4" - "}\n\n" ) - .arg( linkColor, fgColor, bgColor, headerFont ) - + - QString::fromLatin1( "table.encr {\n" - " background-color: %1 ! important;\n" - "}\n\n" - - "tr.encrH {\n" - " background-color: %2 ! important;\n" - "%3" - "}\n\n" - - "tr.encrB { background-color: %4 ! important; }\n\n" ) - .arg( cPgpEncrF.name(), - cPgpEncrH.name(), - headerFont, - cPgpEncrB.name() ) - + - QString::fromLatin1( "table.signOkKeyOk {\n" - " background-color: %1 ! important;\n" - "}\n\n" - - "tr.signOkKeyOkH {\n" - " background-color: %2 ! important;\n" - "%3" - "}\n\n" - - "tr.signOkKeyOkB { background-color: %4 ! important; }\n\n" ) - .arg( cPgpOk1F.name(), - cPgpOk1H.name(), - headerFont, - cPgpOk1B.name() ) - + - QString::fromLatin1( "table.signOkKeyBad {\n" - " background-color: %1 ! important;\n" - "}\n\n" - - "tr.signOkKeyBadH {\n" - " background-color: %2 ! important;\n" - "%3" - "}\n\n" - - "tr.signOkKeyBadB { background-color: %4 ! important; }\n\n" ) - .arg( cPgpOk0F.name(), - cPgpOk0H.name(), - headerFont, - cPgpOk0B.name() ) - + - QString::fromLatin1( "table.signWarn {\n" - " background-color: %1 ! important;\n" - "}\n\n" - - "tr.signWarnH {\n" - " background-color: %2 ! important;\n" - "%3" - "}\n\n" - - "tr.signWarnB { background-color: %4 ! important; }\n\n" ) - .arg( cPgpWarnF.name(), - cPgpWarnH.name(), - headerFont, - cPgpWarnB.name() ) - + - QString::fromLatin1( "table.signErr {\n" - " background-color: %1 ! important;\n" - "}\n\n" - - "tr.signErrH {\n" - " background-color: %2 ! important;\n" - "%3" - "}\n\n" - - "tr.signErrB { background-color: %4 ! important; }\n\n" ) - .arg( cPgpErrF.name(), - cPgpErrH.name(), - headerFont, - cPgpErrB.name() ) - + - QString::fromLatin1( "div.htmlWarn {\n" - " border: 2px solid %1 ! important;\n" - " line-height: normal;\n" - "}\n\n" ) - .arg( cHtmlWarning.name() ) - + - QString::fromLatin1( "div.header {\n" - "%1" - "}\n\n" - - "div.fancy.header > div {\n" - " background-color: %2 ! important;\n" - " color: %3 ! important;\n" - " border: solid %4 1px ! important;\n" - " line-height: normal;\n" - "}\n\n" - - "div.fancy.header > div a[href] { color: %3 ! important; }\n\n" - - "div.fancy.header > div a[href]:hover { text-decoration: underline ! important; }\n\n" - - "div.fancy.header > div.spamheader {\n" - " background-color: #cdcdcd ! important;\n" - " border-top: 0px ! important;\n" - " padding: 3px ! important;\n" - " color: black ! important;\n" - " font-weight: bold ! important;\n" - " font-size: smaller ! important;\n" - "}\n\n" - - "div.fancy.header > table.outer {\n" - " background-color: %5 ! important;\n" - " color: %4 ! important;\n" - " border-bottom: solid %4 1px ! important;\n" - " border-left: solid %4 1px ! important;\n" - " border-right: solid %4 1px ! important;\n" - "}\n\n" - - "div.senderpic{\n" - " padding: 0px ! important;\n" - " font-size:0.8em ! important;\n" - " border:1px solid %6 ! important;\n" - // FIXME: InfoBackground crashes KHTML - //" background-color:InfoBackground ! important;\n" - " background-color:%5 ! important;\n" - "}\n\n" - - "div.senderstatus{\n" - " text-align:center ! important;\n" - "}\n\n" - ) - - .arg( headerFont ) - .arg( pal.color( QPalette::Highlight ).name(), - pal.color( QPalette::HighlightedText ).name(), - pal.color( QPalette::Foreground ).name(), - pal.color( QPalette::Background ).name() ) - .arg( pal.color( QPalette::Mid ).name() ) - + quoteCSS; - } + QString::fromLatin1( "body {\n" + " font-family: \"%1\" ! important;\n" + " font-size: %2 ! important;\n" + " color: %3 ! important;\n" + "%4" + "}\n\n" ) + .arg( bodyFont( fixed ).family(), + bodyFontSize, + fgColor, + background ) + + + /* This shouldn't be necessary because font properties are inherited + automatically and causes wrong font settings with QTextBrowser + because it doesn't understand the inherit statement + QString::fromLatin1( "table {\n" + " font-family: inherit ! important;\n" + " font-size: inherit ! important;\n" + " font-weight: inherit ! important;\n" + "}\n\n" ) + + + */ + QString::fromLatin1( "a {\n" + " color: %1 ! important;\n" + " text-decoration: none ! important;\n" + "}\n\n" + + "a.white {\n" + " color: white ! important;\n" + "}\n\n" + + "a.black {\n" + " color: black ! important;\n" + "}\n\n" + + "table.textAtm { background-color: %2 ! important; }\n\n" + + "tr.textAtmH {\n" + " background-color: %3 ! important;\n" + "%4" + "}\n\n" + + "tr.textAtmB {\n" + " background-color: %3 ! important;\n" + "}\n\n" + + "table.signInProgress,\n" + "table.rfc822 {\n" + " background-color: %3 ! important;\n" + "}\n\n" + + "tr.signInProgressH,\n" + "tr.rfc822H {\n" + "%4" + "}\n\n" ) + .arg( linkColor, fgColor, bgColor, headerFont ) + + + QString::fromLatin1( "table.encr {\n" + " background-color: %1 ! important;\n" + "}\n\n" + + "tr.encrH {\n" + " background-color: %2 ! important;\n" + "%3" + "}\n\n" + + "tr.encrB { background-color: %4 ! important; }\n\n" ) + .arg( cPgpEncrF.name(), + cPgpEncrH.name(), + headerFont, + cPgpEncrB.name() ) + + + QString::fromLatin1( "table.signOkKeyOk {\n" + " background-color: %1 ! important;\n" + "}\n\n" + + "tr.signOkKeyOkH {\n" + " background-color: %2 ! important;\n" + "%3" + "}\n\n" + + "tr.signOkKeyOkB { background-color: %4 ! important; }\n\n" ) + .arg( cPgpOk1F.name(), + cPgpOk1H.name(), + headerFont, + cPgpOk1B.name() ) + + + QString::fromLatin1( "table.signOkKeyBad {\n" + " background-color: %1 ! important;\n" + "}\n\n" + + "tr.signOkKeyBadH {\n" + " background-color: %2 ! important;\n" + "%3" + "}\n\n" + + "tr.signOkKeyBadB { background-color: %4 ! important; }\n\n" ) + .arg( cPgpOk0F.name(), + cPgpOk0H.name(), + headerFont, + cPgpOk0B.name() ) + + + QString::fromLatin1( "table.signWarn {\n" + " background-color: %1 ! important;\n" + "}\n\n" + + "tr.signWarnH {\n" + " background-color: %2 ! important;\n" + "%3" + "}\n\n" + + "tr.signWarnB { background-color: %4 ! important; }\n\n" ) + .arg( cPgpWarnF.name(), + cPgpWarnH.name(), + headerFont, + cPgpWarnB.name() ) + + + QString::fromLatin1( "table.signErr {\n" + " background-color: %1 ! important;\n" + "}\n\n" + + "tr.signErrH {\n" + " background-color: %2 ! important;\n" + "%3" + "}\n\n" + + "tr.signErrB { background-color: %4 ! important; }\n\n" ) + .arg( cPgpErrF.name(), + cPgpErrH.name(), + headerFont, + cPgpErrB.name() ) + + + QString::fromLatin1( "div.htmlWarn {\n" + " border: 2px solid %1 ! important;\n" + " line-height: normal;\n" + "}\n\n" ) + .arg( cHtmlWarning.name() ) + + + QString::fromLatin1( "div.header {\n" + "%1" + "}\n\n" + + "div.fancy.header > div {\n" + " background-color: %2 ! important;\n" + " color: %3 ! important;\n" + " border: solid %4 1px ! important;\n" + " line-height: normal;\n" + "}\n\n" + + "div.fancy.header > div a[href] { color: %3 ! important; }\n\n" + + "div.fancy.header > div a[href]:hover { text-decoration: underline ! important; }\n\n" + + "div.fancy.header > div.spamheader {\n" + " background-color: #cdcdcd ! important;\n" + " border-top: 0px ! important;\n" + " padding: 3px ! important;\n" + " color: black ! important;\n" + " font-weight: bold ! important;\n" + " font-size: smaller ! important;\n" + "}\n\n" + + "div.fancy.header > table.outer {\n" + " background-color: %5 ! important;\n" + " color: %4 ! important;\n" + " border-bottom: solid %4 1px ! important;\n" + " border-left: solid %4 1px ! important;\n" + " border-right: solid %4 1px ! important;\n" + "}\n\n" + + "div.senderpic{\n" + " padding: 0px ! important;\n" + " font-size:0.8em ! important;\n" + " border:1px solid %6 ! important;\n" + // FIXME: InfoBackground crashes KHTML + //" background-color:InfoBackground ! important;\n" + " background-color:%5 ! important;\n" + "}\n\n" + + "div.senderstatus{\n" + " text-align:center ! important;\n" + "}\n\n" + ) + + .arg( headerFont ) + .arg( pal.color( QPalette::Highlight ).name(), + pal.color( QPalette::HighlightedText ).name(), + pal.color( QPalette::Foreground ).name(), + pal.color( QPalette::Background ).name() ) + .arg( pal.color( QPalette::Mid ).name() ) + + quoteCSS; +} - QString CSSHelperBase::commonCssDefinitions() const { +QString CSSHelperBase::commonCssDefinitions() const { const QPalette & pal = QApplication::palette(); const QString headerFont = QString::fromLatin1("font-family: \"%1\" ! important;\n" - " font-size: %2px ! important;\n") - .arg( mBodyFont.family() ) - .arg( pointsToPixel( this->mPaintDevice, mBodyFont.pointSize() ) ); + " font-size: %2px ! important;\n") + .arg( mBodyFont.family() ) + .arg( pointsToPixel( this->mPaintDevice, mBodyFont.pointSize() ) ); return - QString::fromLatin1("div.header {\n" - " margin-bottom: 10pt ! important;\n" - "}\n\n" - - "table.textAtm {\n" - " margin-top: 10pt ! important;\n" - " margin-bottom: 10pt ! important;\n" - "}\n\n" - - "tr.textAtmH,\n" - "tr.textAtmB,\n" - "tr.rfc822B {\n" - " font-weight: normal ! important;\n" - "}\n\n" - - "tr.signInProgressH,\n" - "tr.rfc822H,\n" - "tr.encrH,\n" - "tr.signOkKeyOkH,\n" - "tr.signOkKeyBadH,\n" - "tr.signWarnH,\n" - "tr.signErrH {\n" - " font-weight: bold ! important;\n" - "}\n\n" - - "tr.textAtmH td,\n" - "tr.textAtmB td {\n" - " padding: 3px ! important;\n" - "}\n\n" - - "table.rfc822 {\n" - " width: 100% ! important;\n" - " border: solid 1px black ! important;\n" - " margin-top: 10pt ! important;\n" - " margin-bottom: 10pt ! important;\n" - "}\n\n" - - "table.textAtm,\n" - "table.encr,\n" - "table.signWarn,\n" - "table.signErr,\n" - "table.signOkKeyBad,\n" - "table.signOkKeyOk,\n" - "table.signInProgress,\n" - "div.fancy.header table {\n" - " width: 100% ! important;\n" - " border-width: 0px ! important;\n" - " line-height: normal;\n" - "}\n\n" - - "div.htmlWarn {\n" - " margin: 0px 5% ! important;\n" - " padding: 10px ! important;\n" - " text-align: left ! important;\n" - " line-height: normal;\n" - "}\n\n" - - "div.fancy.header > div {\n" - " font-weight: bold ! important;\n" - " padding: 4px ! important;\n" - " line-height: normal;\n" - "}\n\n" - - "div.fancy.header table {\n" - " padding: 2px ! important;\n" // ### khtml bug: this is ignored - " text-align: left ! important;\n" - " border-collapse: separate ! important;\n" - "}\n\n" - - "div.fancy.header table th {\n" - " %3\n" - " padding: 0px ! important;\n" - " white-space: nowrap ! important;\n" - " border-spacing: 0px ! important;\n" - " text-align: left ! important;\n" - " vertical-align: top ! important;\n" - " background-color: %1 ! important;\n" - " color: %2 ! important;\n" - " border: 1px ! important;\n" - - "}\n\n" - - "div.fancy.header table td {\n" - " %3\n" - " padding: 0px ! important;\n" - " border-spacing: 0px ! important;\n" - " text-align: left ! important;\n" - " vertical-align: top ! important;\n" - " width: 100% ! important;\n" - " background-color: %1 ! important;\n" - " color: %2 ! important;\n" - " border: 1px ! important;\n" - "}\n\n" - - - "div.fancy.header table a:hover {\n" - " background-color: transparent ! important;\n" - "}\n\n" - - "span.pimsmileytext {\n" - " position: absolute;\n" - " top: 0px;\n" - " left: 0px;\n" - " visibility: hidden;\n" - "}\n\n" - - "img.pimsmileyimg {\n" - "}\n\n" - - "div.quotelevelmark {\n" - " position: absolute;\n" - " margin-left:-10px;\n" - "}\n\n").arg( pal.color( QPalette::Background ).name() ).arg(pal.color( QPalette::Foreground ).name()).arg(headerFont) - ; - } + QString::fromLatin1("div.header {\n" + " margin-bottom: 10pt ! important;\n" + "}\n\n" + + "table.textAtm {\n" + " margin-top: 10pt ! important;\n" + " margin-bottom: 10pt ! important;\n" + "}\n\n" + + "tr.textAtmH,\n" + "tr.textAtmB,\n" + "tr.rfc822B {\n" + " font-weight: normal ! important;\n" + "}\n\n" + + "tr.signInProgressH,\n" + "tr.rfc822H,\n" + "tr.encrH,\n" + "tr.signOkKeyOkH,\n" + "tr.signOkKeyBadH,\n" + "tr.signWarnH,\n" + "tr.signErrH {\n" + " font-weight: bold ! important;\n" + "}\n\n" + + "tr.textAtmH td,\n" + "tr.textAtmB td {\n" + " padding: 3px ! important;\n" + "}\n\n" + + "table.rfc822 {\n" + " width: 100% ! important;\n" + " border: solid 1px black ! important;\n" + " margin-top: 10pt ! important;\n" + " margin-bottom: 10pt ! important;\n" + "}\n\n" + + "table.textAtm,\n" + "table.encr,\n" + "table.signWarn,\n" + "table.signErr,\n" + "table.signOkKeyBad,\n" + "table.signOkKeyOk,\n" + "table.signInProgress,\n" + "div.fancy.header table {\n" + " width: 100% ! important;\n" + " border-width: 0px ! important;\n" + " line-height: normal;\n" + "}\n\n" + + "div.htmlWarn {\n" + " margin: 0px 5% ! important;\n" + " padding: 10px ! important;\n" + " text-align: left ! important;\n" + " line-height: normal;\n" + "}\n\n" + + "div.fancy.header > div {\n" + " font-weight: bold ! important;\n" + " padding: 4px ! important;\n" + " line-height: normal;\n" + "}\n\n" + + "div.fancy.header table {\n" + " padding: 2px ! important;\n" // ### khtml bug: this is ignored + " text-align: left ! important;\n" + " border-collapse: separate ! important;\n" + "}\n\n" + + "div.fancy.header table th {\n" + " %3\n" + " padding: 0px ! important;\n" + " white-space: nowrap ! important;\n" + " border-spacing: 0px ! important;\n" + " text-align: left ! important;\n" + " vertical-align: top ! important;\n" + " background-color: %1 ! important;\n" + " color: %2 ! important;\n" + " border: 1px ! important;\n" + + "}\n\n" + + "div.fancy.header table td {\n" + " %3\n" + " padding: 0px ! important;\n" + " border-spacing: 0px ! important;\n" + " text-align: left ! important;\n" + " vertical-align: top ! important;\n" + " width: 100% ! important;\n" + " background-color: %1 ! important;\n" + " color: %2 ! important;\n" + " border: 1px ! important;\n" + "}\n\n" + + + "div.fancy.header table a:hover {\n" + " background-color: transparent ! important;\n" + "}\n\n" + + "span.pimsmileytext {\n" + " position: absolute;\n" + " top: 0px;\n" + " left: 0px;\n" + " visibility: hidden;\n" + "}\n\n" + + "img.pimsmileyimg {\n" + "}\n\n" + + "div.quotelevelmark {\n" + " position: absolute;\n" + " margin-left:-10px;\n" + "}\n\n").arg( pal.color( QPalette::Background ).name() ).arg(pal.color( QPalette::Foreground ).name()).arg(headerFont) + ; +} - void CSSHelperBase::setBodyFont( const QFont& font ) - { +void CSSHelperBase::setBodyFont( const QFont& font ) +{ mBodyFont = font; - } +} - void CSSHelperBase::setPrintFont( const QFont& font ) - { +void CSSHelperBase::setPrintFont( const QFont& font ) +{ mPrintFont = font; - } +} - QColor CSSHelperBase::quoteColor( int level ) - { +QColor CSSHelperBase::quoteColor( int level ) +{ const int actualLevel = qMin( qMax( level, 0 ), 2 ); return mQuoteColor[actualLevel]; - } +} - QColor CSSHelperBase::pgpWarnColor() const - { +QColor CSSHelperBase::pgpWarnColor() const +{ return cPgpWarnH; - } +} } diff -Nru kdepim-4.12.97/messageviewer/viewer/csshelperbase.h kdepim-4.13.0/messageviewer/viewer/csshelperbase.h --- kdepim-4.12.97/messageviewer/viewer/csshelperbase.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/csshelperbase.h 2014-04-10 07:40:20.000000000 +0000 @@ -42,7 +42,7 @@ namespace MessageViewer { class MESSAGEVIEWER_EXPORT CSSHelperBase { - public: +public: /** Construct a CSSHelper object and set its font and color settings to default values. Sub-Classes should put their config loading here. @@ -73,12 +73,12 @@ QColor pgpWarnColor() const; - protected: +protected: /** Recalculate PGP frame and body colors (should be called after changing color settings) */ void recalculatePGPColors(); - protected: +protected: QFont mBodyFont, mPrintFont, mFixedFont, mFixedPrintFont; QFont mQuoteFont[3]; QColor mQuoteColor[3]; @@ -96,16 +96,16 @@ // color of frame of warning preceding the source of HTML messages QColor cHtmlWarning; - private: +private: int fontSize( bool fixed, bool print = false ) const; - // returns CSS rules specific to the print media type + // returns CSS rules specific to the print media type QString printCssDefinitions( bool fixed ) const; // returns CSS rules specific to the screen media type QString screenCssDefinitions( const CSSHelperBase * helper, bool fixed ) const; // returns CSS rules common to both screen and print media types QString commonCssDefinitions() const; - private: +private: const QPaintDevice *mPaintDevice; }; diff -Nru kdepim-4.12.97/messageviewer/viewer/csshelper.cpp kdepim-4.13.0/messageviewer/viewer/csshelper.cpp --- kdepim-4.12.97/messageviewer/viewer/csshelper.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/csshelper.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -47,69 +47,69 @@ namespace MessageViewer { CSSHelper::CSSHelper( const QPaintDevice *pd ) : - CSSHelperBase( pd ) + CSSHelperBase( pd ) { - KConfig *config = GlobalSettings::self()->config(); + KConfig *config = GlobalSettings::self()->config(); - KConfigGroup reader( config, "Reader" ); - KConfigGroup fonts( config, "Fonts" ); - KConfigGroup pixmaps( config, "Pixmaps" ); - - mRecycleQuoteColors = reader.readEntry( "RecycleQuoteColors", false ); - - mForegroundColor = KColorScheme( QPalette::Active ).foreground().color(); - if ( !MessageCore::GlobalSettings::self()->useDefaultColors() ) { - mLinkColor = - reader.readEntry( "LinkColor", mLinkColor ); - mVisitedLinkColor = - reader.readEntry( "FollowedColor", mVisitedLinkColor ); - cPgpEncrH = - reader.readEntry( "PGPMessageEncr", cPgpEncrH ); - cPgpOk1H = - reader.readEntry( "PGPMessageOkKeyOk", cPgpOk1H ); - cPgpOk0H = - reader.readEntry( "PGPMessageOkKeyBad", cPgpOk0H ); - cPgpWarnH = - reader.readEntry( "PGPMessageWarn", cPgpWarnH ); - cPgpErrH = - reader.readEntry( "PGPMessageErr", cPgpErrH ); - cHtmlWarning = - reader.readEntry( "HTMLWarningColor", cHtmlWarning ); - for ( int i = 0 ; i < 3 ; ++i ) { - const QString key = QLatin1String("QuotedText") + QString::number( i+1 ); - mQuoteColor[i] = reader.readEntry( key, mQuoteColor[i] ); + KConfigGroup reader( config, "Reader" ); + KConfigGroup fonts( config, "Fonts" ); + KConfigGroup pixmaps( config, "Pixmaps" ); + + mRecycleQuoteColors = reader.readEntry( "RecycleQuoteColors", false ); + + mForegroundColor = KColorScheme( QPalette::Active ).foreground().color(); + if ( !MessageCore::GlobalSettings::self()->useDefaultColors() ) { + mLinkColor = + reader.readEntry( "LinkColor", mLinkColor ); + mVisitedLinkColor = + reader.readEntry( "FollowedColor", mVisitedLinkColor ); + cPgpEncrH = + reader.readEntry( "PGPMessageEncr", cPgpEncrH ); + cPgpOk1H = + reader.readEntry( "PGPMessageOkKeyOk", cPgpOk1H ); + cPgpOk0H = + reader.readEntry( "PGPMessageOkKeyBad", cPgpOk0H ); + cPgpWarnH = + reader.readEntry( "PGPMessageWarn", cPgpWarnH ); + cPgpErrH = + reader.readEntry( "PGPMessageErr", cPgpErrH ); + cHtmlWarning = + reader.readEntry( "HTMLWarningColor", cHtmlWarning ); + for ( int i = 0 ; i < 3 ; ++i ) { + const QString key = QLatin1String("QuotedText") + QString::number( i+1 ); + mQuoteColor[i] = reader.readEntry( key, mQuoteColor[i] ); + } + mBackgroundColor = reader.readEntry( "BackgroundColor", mBackgroundColor ); } - mBackgroundColor = reader.readEntry( "BackgroundColor", mBackgroundColor ); - } - if ( !MessageCore::GlobalSettings::self()->useDefaultFonts() ) { - mBodyFont = fonts.readEntry( "body-font", mBodyFont ); - mPrintFont = fonts.readEntry( "print-font", mPrintFont ); - mFixedFont = fonts.readEntry( "fixed-font", mFixedFont ); - mFixedPrintFont = mFixedFont; // FIXME when we have a separate fixed print font - QFont defaultFont = mBodyFont; - defaultFont.setItalic( true ); - for ( int i = 0 ; i < 3 ; ++i ) { - const QString key = QString::fromLatin1( "quote%1-font" ).arg( i+1 ); - mQuoteFont[i] = fonts.readEntry( key, defaultFont ); + if ( !MessageCore::GlobalSettings::self()->useDefaultFonts() ) { + mBodyFont = fonts.readEntry( "body-font", mBodyFont ); + mPrintFont = fonts.readEntry( "print-font", mPrintFont ); + mFixedFont = fonts.readEntry( "fixed-font", mFixedFont ); + mFixedPrintFont = mFixedFont; // FIXME when we have a separate fixed print font + QFont defaultFont = mBodyFont; + defaultFont.setItalic( true ); + for ( int i = 0 ; i < 3 ; ++i ) { + const QString key = QString::fromLatin1( "quote%1-font" ).arg( i+1 ); + mQuoteFont[i] = fonts.readEntry( key, defaultFont ); + } } - } - mShrinkQuotes = GlobalSettings::self()->shrinkQuotes(); + mShrinkQuotes = GlobalSettings::self()->shrinkQuotes(); - mBackingPixmapStr = pixmaps.readPathEntry("Readerwin", QString()); - mBackingPixmapOn = !mBackingPixmapStr.isEmpty(); + mBackingPixmapStr = pixmaps.readPathEntry("Readerwin", QString()); + mBackingPixmapOn = !mBackingPixmapStr.isEmpty(); - recalculatePGPColors(); + recalculatePGPColors(); } QString CSSHelper::htmlHead( bool fixed ) const { - return - QLatin1String("\n" - "\n" - "\n"); + return + QLatin1String("\n" + "\n" + "\n"); } } diff -Nru kdepim-4.12.97/messageviewer/viewer/csshelper.h kdepim-4.13.0/messageviewer/viewer/csshelper.h --- kdepim-4.12.97/messageviewer/viewer/csshelper.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/csshelper.h 2014-04-10 07:40:20.000000000 +0000 @@ -41,11 +41,11 @@ class MESSAGEVIEWER_EXPORT CSSHelper : public CSSHelperBase { public: - explicit CSSHelper( const QPaintDevice *pd ); + explicit CSSHelper( const QPaintDevice *pd ); - /** @return HTML head including style sheet definitions and the + /** @return HTML head including style sheet definitions and the >body< tag */ - QString htmlHead( bool fixedFont = false ) const; + QString htmlHead( bool fixedFont = false ) const; }; } diff -Nru kdepim-4.12.97/messageviewer/viewer/editorwatcher.cpp kdepim-4.13.0/messageviewer/viewer/editorwatcher.cpp --- kdepim-4.12.97/messageviewer/viewer/editorwatcher.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/editorwatcher.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -55,125 +55,125 @@ mFileModified( true ), // assume the worst unless we know better mDone( false ) { - assert( mUrl.isLocalFile() ); - mTimer.setSingleShot( true ); - connect( &mTimer, SIGNAL(timeout()), SLOT(checkEditDone()) ); + assert( mUrl.isLocalFile() ); + mTimer.setSingleShot( true ); + connect( &mTimer, SIGNAL(timeout()), SLOT(checkEditDone()) ); } bool EditorWatcher::start() { - // find an editor - KUrl::List list; - list.append( mUrl ); - KService::Ptr offer = KMimeTypeTrader::self()->preferredService( mMimeType, QLatin1String("Application") ); - if ( mOpenWith || !offer ) { - AutoQPointer dlg( new KOpenWithDialog( list, i18n("Edit with:"), - QString(), mParentWidget ) ); - const int dlgrc = dlg->exec(); - if ( dlgrc && dlg ) { - offer = dlg->service(); + // find an editor + KUrl::List list; + list.append( mUrl ); + KService::Ptr offer = KMimeTypeTrader::self()->preferredService( mMimeType, QLatin1String("Application") ); + if ( mOpenWith || !offer ) { + AutoQPointer dlg( new KOpenWithDialog( list, i18n("Edit with:"), + QString(), mParentWidget ) ); + const int dlgrc = dlg->exec(); + if ( dlgrc && dlg ) { + offer = dlg->service(); + } + if ( !dlgrc || !offer ) + return false; } - if ( !dlgrc || !offer ) - return false; - } #ifdef HAVE_SYS_INOTIFY_H - // monitor file - mInotifyFd = inotify_init(); - if ( mInotifyFd > 0 ) { - mInotifyWatch = inotify_add_watch( mInotifyFd, mUrl.path().toLatin1(), IN_CLOSE | IN_OPEN | IN_MODIFY ); - if ( mInotifyWatch >= 0 ) { - QSocketNotifier *sn = new QSocketNotifier( mInotifyFd, QSocketNotifier::Read, this ); - connect( sn, SIGNAL(activated(int)), SLOT(inotifyEvent()) ); - mHaveInotify = true; - mFileModified = false; + // monitor file + mInotifyFd = inotify_init(); + if ( mInotifyFd > 0 ) { + mInotifyWatch = inotify_add_watch( mInotifyFd, mUrl.path().toLatin1(), IN_CLOSE | IN_OPEN | IN_MODIFY ); + if ( mInotifyWatch >= 0 ) { + QSocketNotifier *sn = new QSocketNotifier( mInotifyFd, QSocketNotifier::Read, this ); + connect( sn, SIGNAL(activated(int)), SLOT(inotifyEvent()) ); + mHaveInotify = true; + mFileModified = false; + } + } else { + kWarning() << "Failed to activate INOTIFY!"; } - } else { - kWarning() << "Failed to activate INOTIFY!"; - } #endif - // start the editor - const QStringList params = KRun::processDesktopExec( *offer, list, false ); - mEditor = new KProcess( this ); - mEditor->setProgram( params ); - connect( mEditor, SIGNAL(finished(int,QProcess::ExitStatus)), - SLOT(editorExited()) ); - mEditor->start(); - if ( !mEditor->waitForStarted() ) - return false; - mEditorRunning = true; + // start the editor + const QStringList params = KRun::processDesktopExec( *offer, list, false ); + mEditor = new KProcess( this ); + mEditor->setProgram( params ); + connect( mEditor, SIGNAL(finished(int,QProcess::ExitStatus)), + SLOT(editorExited()) ); + mEditor->start(); + if ( !mEditor->waitForStarted() ) + return false; + mEditorRunning = true; - mEditTime.start(); - return true; + mEditTime.start(); + return true; } void EditorWatcher::inotifyEvent() { - assert( mHaveInotify ); + assert( mHaveInotify ); #ifdef HAVE_SYS_INOTIFY_H - int pending = -1; - char buffer[4096]; - ioctl( mInotifyFd, FIONREAD, &pending ); - while ( pending > 0 ) { - int size = read( mInotifyFd, buffer, qMin( pending, (int)sizeof(buffer) ) ); - pending -= size; - if ( size < 0 ) - break; // error - int offset = 0; - while ( size > 0 ) { - struct inotify_event *event = (struct inotify_event *) &buffer[offset]; - size -= sizeof( struct inotify_event ) + event->len; - offset += sizeof( struct inotify_event ) + event->len; - if ( event->mask & IN_OPEN ) - mFileOpen = true; - if ( event->mask & IN_CLOSE ) - mFileOpen = false; - if ( event->mask & IN_MODIFY ) - mFileModified = true; + int pending = -1; + char buffer[4096]; + ioctl( mInotifyFd, FIONREAD, &pending ); + while ( pending > 0 ) { + int size = read( mInotifyFd, buffer, qMin( pending, (int)sizeof(buffer) ) ); + pending -= size; + if ( size < 0 ) + break; // error + int offset = 0; + while ( size > 0 ) { + struct inotify_event *event = (struct inotify_event *) &buffer[offset]; + size -= sizeof( struct inotify_event ) + event->len; + offset += sizeof( struct inotify_event ) + event->len; + if ( event->mask & IN_OPEN ) + mFileOpen = true; + if ( event->mask & IN_CLOSE ) + mFileOpen = false; + if ( event->mask & IN_MODIFY ) + mFileModified = true; + } } - } #endif - mTimer.start( 500 ); + mTimer.start( 500 ); } void EditorWatcher::editorExited() { - mEditorRunning = false; - mTimer.start( 500 ); + mEditorRunning = false; + mTimer.start( 500 ); } void EditorWatcher::checkEditDone() { - if ( mEditorRunning || (mFileOpen && mHaveInotify) || mDone ) - return; + if ( mEditorRunning || (mFileOpen && mHaveInotify) || mDone ) + return; - static QStringList readOnlyMimeTypes; - if ( readOnlyMimeTypes.isEmpty() ) { - readOnlyMimeTypes << QLatin1String("message/rfc822") - << QLatin1String("application/pdf"); - } - - // protect us against double-deletion by calling this method again while - // the subeventloop of the message box is running - mDone = true; - - // check if it's a mime type that's mostly handled read-only - const bool isReadOnlyMimeType = ( readOnlyMimeTypes.contains( mMimeType ) || - mMimeType.startsWith( QLatin1String("image/") ) ); - - // nobody can edit that fast, we seem to be unable to detect - // when the editor will be closed - if ( mEditTime.elapsed() <= 3000 && !isReadOnlyMimeType ) { - KMessageBox::information( mParentWidget, - i18n( "KMail is unable to detect when the chosen editor is closed. " - "To avoid data loss, editing the attachment will be aborted." ), - i18n( "Unable to edit attachment" ), - QLatin1String("UnableToEditAttachment") ); - } + static QStringList readOnlyMimeTypes; + if ( readOnlyMimeTypes.isEmpty() ) { + readOnlyMimeTypes << QLatin1String("message/rfc822") + << QLatin1String("application/pdf"); + } + + // protect us against double-deletion by calling this method again while + // the subeventloop of the message box is running + mDone = true; + + // check if it's a mime type that's mostly handled read-only + const bool isReadOnlyMimeType = ( readOnlyMimeTypes.contains( mMimeType ) || + mMimeType.startsWith( QLatin1String("image/") ) ); + + // nobody can edit that fast, we seem to be unable to detect + // when the editor will be closed + if ( mEditTime.elapsed() <= 3000 && !isReadOnlyMimeType ) { + KMessageBox::information( mParentWidget, + i18n( "KMail is unable to detect when the chosen editor is closed. " + "To avoid data loss, editing the attachment will be aborted." ), + i18n( "Unable to edit attachment" ), + QLatin1String("UnableToEditAttachment") ); + } - emit editDone( this ); - deleteLater(); + emit editDone( this ); + deleteLater(); } } diff -Nru kdepim-4.12.97/messageviewer/viewer/editorwatcher.h kdepim-4.13.0/messageviewer/viewer/editorwatcher.h --- kdepim-4.12.97/messageviewer/viewer/editorwatcher.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/editorwatcher.h 2014-04-10 07:40:20.000000000 +0000 @@ -38,8 +38,8 @@ */ class MESSAGEVIEWER_EXPORT EditorWatcher : public QObject { - Q_OBJECT - public: + Q_OBJECT +public: /** * Constructs an EditorWatcher. @@ -54,15 +54,15 @@ bool start(); bool fileChanged() const { return mFileModified; } KUrl url() const { return mUrl;} - signals: +signals: void editDone( MessageViewer::EditorWatcher* watcher ); - private slots: +private slots: void editorExited(); void inotifyEvent(); void checkEditDone(); - private: +private: KUrl mUrl; QString mMimeType; bool mOpenWith; diff -Nru kdepim-4.12.97/messageviewer/viewer/htmlquotecolorer.h kdepim-4.13.0/messageviewer/viewer/htmlquotecolorer.h --- kdepim-4.12.97/messageviewer/viewer/htmlquotecolorer.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/htmlquotecolorer.h 2014-04-10 07:40:20.000000000 +0000 @@ -30,7 +30,7 @@ */ class HTMLQuoteColorer { - public: +public: explicit HTMLQuoteColorer(); @@ -51,7 +51,7 @@ */ QString process(const QString &htmlSource , QString &extraHead); - private: +private: QColor mQuoteColors[3]; }; diff -Nru kdepim-4.12.97/messageviewer/viewer/kleojobexecutor.cpp kdepim-4.13.0/messageviewer/viewer/kleojobexecutor.cpp --- kdepim-4.12.97/messageviewer/viewer/kleojobexecutor.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/kleojobexecutor.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -39,124 +39,124 @@ KleoJobExecutor::KleoJobExecutor( QObject* parent ) : QObject( parent ) { - setObjectName( QLatin1String("KleoJobExecutor") ); - mEventLoop = new QEventLoop( this ); + setObjectName( QLatin1String("KleoJobExecutor") ); + mEventLoop = new QEventLoop( this ); } GpgME::VerificationResult KleoJobExecutor::exec( - Kleo::VerifyDetachedJob* job, - const QByteArray & signature, - const QByteArray & signedData ) -{ - kDebug() << "Starting detached verification job"; - connect( job, SIGNAL(result(GpgME::VerificationResult)), - SLOT(verificationResult(GpgME::VerificationResult)) ); - GpgME::Error err = job->start( signature, signedData ); - if ( err ) - return VerificationResult( err ); - mEventLoop->exec( QEventLoop::ExcludeUserInputEvents ); - return mVerificationResult; + Kleo::VerifyDetachedJob* job, + const QByteArray & signature, + const QByteArray & signedData ) +{ + kDebug() << "Starting detached verification job"; + connect( job, SIGNAL(result(GpgME::VerificationResult)), + SLOT(verificationResult(GpgME::VerificationResult)) ); + GpgME::Error err = job->start( signature, signedData ); + if ( err ) + return VerificationResult( err ); + mEventLoop->exec( QEventLoop::ExcludeUserInputEvents ); + return mVerificationResult; } GpgME::VerificationResult KleoJobExecutor::exec( - Kleo::VerifyOpaqueJob * job, - const QByteArray & signedData, - QByteArray & plainText ) -{ - kDebug() << "Starting opaque verification job"; - connect( job, SIGNAL(result(GpgME::VerificationResult,QByteArray)), - SLOT(verificationResult(GpgME::VerificationResult,QByteArray)) ); - GpgME::Error err = job->start( signedData ); - if ( err ) { - plainText.clear(); - return VerificationResult( err ); - } - mEventLoop->exec( QEventLoop::ExcludeUserInputEvents ); - plainText = mData; - return mVerificationResult; + Kleo::VerifyOpaqueJob * job, + const QByteArray & signedData, + QByteArray & plainText ) +{ + kDebug() << "Starting opaque verification job"; + connect( job, SIGNAL(result(GpgME::VerificationResult,QByteArray)), + SLOT(verificationResult(GpgME::VerificationResult,QByteArray)) ); + GpgME::Error err = job->start( signedData ); + if ( err ) { + plainText.clear(); + return VerificationResult( err ); + } + mEventLoop->exec( QEventLoop::ExcludeUserInputEvents ); + plainText = mData; + return mVerificationResult; } std::pair< GpgME::DecryptionResult, GpgME::VerificationResult > KleoJobExecutor::exec( - Kleo::DecryptVerifyJob * job, - const QByteArray & cipherText, - QByteArray & plainText ) -{ - kDebug() << "Starting decryption job"; - connect( job, SIGNAL(result(GpgME::DecryptionResult,GpgME::VerificationResult,QByteArray)), - SLOT(decryptResult(GpgME::DecryptionResult,GpgME::VerificationResult,QByteArray)) ); - GpgME::Error err = job->start( cipherText ); - if ( err ) { - plainText.clear(); - return std::make_pair( DecryptionResult( err ), VerificationResult( err ) ); - } - mEventLoop->exec( QEventLoop::ExcludeUserInputEvents ); - plainText = mData; - return std::make_pair( mDecryptResult, mVerificationResult ); + Kleo::DecryptVerifyJob * job, + const QByteArray & cipherText, + QByteArray & plainText ) +{ + kDebug() << "Starting decryption job"; + connect( job, SIGNAL(result(GpgME::DecryptionResult,GpgME::VerificationResult,QByteArray)), + SLOT(decryptResult(GpgME::DecryptionResult,GpgME::VerificationResult,QByteArray)) ); + GpgME::Error err = job->start( cipherText ); + if ( err ) { + plainText.clear(); + return std::make_pair( DecryptionResult( err ), VerificationResult( err ) ); + } + mEventLoop->exec( QEventLoop::ExcludeUserInputEvents ); + plainText = mData; + return std::make_pair( mDecryptResult, mVerificationResult ); } GpgME::ImportResult KleoJobExecutor::exec(Kleo::ImportJob* job, const QByteArray & certData) { - connect( job, SIGNAL(result(GpgME::ImportResult)), SLOT(importResult(GpgME::ImportResult)) ); - GpgME::Error err = job->start( certData ); - if ( err ) - return ImportResult( err ); - mEventLoop->exec( QEventLoop::ExcludeUserInputEvents ); - return mImportResult; + connect( job, SIGNAL(result(GpgME::ImportResult)), SLOT(importResult(GpgME::ImportResult)) ); + GpgME::Error err = job->start( certData ); + if ( err ) + return ImportResult( err ); + mEventLoop->exec( QEventLoop::ExcludeUserInputEvents ); + return mImportResult; } void KleoJobExecutor::verificationResult(const GpgME::VerificationResult & result) { - kDebug() << "Detached verification job finished"; - Kleo::Job * job = dynamic_cast( sender() ); - assert(job); - mVerificationResult = result; - mAuditLogError = job->auditLogError(); - mAuditLog = job->auditLogAsHtml(); - mEventLoop->quit(); + kDebug() << "Detached verification job finished"; + Kleo::Job * job = dynamic_cast( sender() ); + assert(job); + mVerificationResult = result; + mAuditLogError = job->auditLogError(); + mAuditLog = job->auditLogAsHtml(); + mEventLoop->quit(); } void KleoJobExecutor::verificationResult(const GpgME::VerificationResult & result, const QByteArray & plainText) { - kDebug() << "Opaque verification job finished"; - Kleo::Job * job = dynamic_cast( sender() ); - assert(job); - mVerificationResult = result; - mData = plainText; - mAuditLogError = job->auditLogError(); - mAuditLog = job->auditLogAsHtml(); - mEventLoop->quit(); + kDebug() << "Opaque verification job finished"; + Kleo::Job * job = dynamic_cast( sender() ); + assert(job); + mVerificationResult = result; + mData = plainText; + mAuditLogError = job->auditLogError(); + mAuditLog = job->auditLogAsHtml(); + mEventLoop->quit(); } void KleoJobExecutor::decryptResult( - const GpgME::DecryptionResult & decryptionresult, - const GpgME::VerificationResult & verificationresult, - const QByteArray & plainText ) -{ - kDebug() << "Decryption job finished"; - Kleo::Job * job = dynamic_cast( sender() ); - assert(job); - mVerificationResult = verificationresult; - mDecryptResult = decryptionresult; - mData = plainText; - mAuditLogError = job->auditLogError(); - mAuditLog = job->auditLogAsHtml(); - mEventLoop->quit(); + const GpgME::DecryptionResult & decryptionresult, + const GpgME::VerificationResult & verificationresult, + const QByteArray & plainText ) +{ + kDebug() << "Decryption job finished"; + Kleo::Job * job = dynamic_cast( sender() ); + assert(job); + mVerificationResult = verificationresult; + mDecryptResult = decryptionresult; + mData = plainText; + mAuditLogError = job->auditLogError(); + mAuditLog = job->auditLogAsHtml(); + mEventLoop->quit(); } void KleoJobExecutor::importResult(const GpgME::ImportResult & result) { - Kleo::Job * job = dynamic_cast( sender() ); - assert(job); - mImportResult = result; - mAuditLogError = job->auditLogError(); - mAuditLog = job->auditLogAsHtml(); - mEventLoop->quit(); + Kleo::Job * job = dynamic_cast( sender() ); + assert(job); + mImportResult = result; + mAuditLogError = job->auditLogError(); + mAuditLog = job->auditLogAsHtml(); + mEventLoop->quit(); } QString KleoJobExecutor::auditLogAsHtml() const { - return mAuditLog; + return mAuditLog; } diff -Nru kdepim-4.12.97/messageviewer/viewer/kleojobexecutor.h kdepim-4.13.0/messageviewer/viewer/kleojobexecutor.h --- kdepim-4.12.97/messageviewer/viewer/kleojobexecutor.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/kleojobexecutor.h 2014-04-10 07:40:20.000000000 +0000 @@ -30,10 +30,10 @@ class QEventLoop; namespace Kleo { - class DecryptVerifyJob; - class ImportJob; - class VerifyDetachedJob; - class VerifyOpaqueJob; +class DecryptVerifyJob; +class ImportJob; +class VerifyDetachedJob; +class VerifyOpaqueJob; } namespace MessageViewer { @@ -43,8 +43,8 @@ */ class KleoJobExecutor : public QObject { - Q_OBJECT - public: + Q_OBJECT +public: explicit KleoJobExecutor( QObject *parent = 0 ); GpgME::VerificationResult exec( Kleo::VerifyDetachedJob* job, @@ -61,7 +61,7 @@ GpgME::Error auditLogError() const { return mAuditLogError; } QString auditLogAsHtml() const; - private slots: +private slots: void verificationResult( const GpgME::VerificationResult &result ); void verificationResult( const GpgME::VerificationResult &result, const QByteArray &plainText ); void decryptResult( const GpgME::DecryptionResult & decryptionresult, @@ -69,7 +69,7 @@ const QByteArray & plainText ); void importResult( const GpgME::ImportResult &result ); - private: +private: QEventLoop *mEventLoop; GpgME::VerificationResult mVerificationResult; GpgME::DecryptionResult mDecryptResult; diff -Nru kdepim-4.12.97/messageviewer/viewer/mimetreemodel.cpp kdepim-4.13.0/messageviewer/viewer/mimetreemodel.cpp --- kdepim-4.12.97/messageviewer/viewer/mimetreemodel.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/mimetreemodel.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -39,82 +39,82 @@ class MimeTreeModel::Private { - public: +public: Private() : - root ( 0 ) + root ( 0 ) {} // FIXME: this should actually be a member function of ContentIndex int contentIndexUp( KMime::ContentIndex &index ) { - Q_ASSERT( index.isValid() ); - QStringList ids = index.toString().split( QLatin1Char('.') ); - const QString lastId = ids.takeLast(); - index = KMime::ContentIndex( ids.join( QLatin1String(".") ) ); - return lastId.toInt(); + Q_ASSERT( index.isValid() ); + QStringList ids = index.toString().split( QLatin1Char('.') ); + const QString lastId = ids.takeLast(); + index = KMime::ContentIndex( ids.join( QLatin1String(".") ) ); + return lastId.toInt(); } QString descriptionForContent( KMime::Content *content ) { - KMime::Message * const message = dynamic_cast( content ); - if ( message && message->subject( false ) ) - return message->subject()->asUnicodeString(); - const QString name = NodeHelper::fileName( content ); - if ( !name.isEmpty() ) - return name; - if ( content->contentDescription( false ) ) { - const QString desc = content->contentDescription()->asUnicodeString(); - if ( !desc.isEmpty() ) - return desc; - } - return i18n( "body part" ); + KMime::Message * const message = dynamic_cast( content ); + if ( message && message->subject( false ) ) + return message->subject()->asUnicodeString(); + const QString name = NodeHelper::fileName( content ); + if ( !name.isEmpty() ) + return name; + if ( content->contentDescription( false ) ) { + const QString desc = content->contentDescription()->asUnicodeString(); + if ( !desc.isEmpty() ) + return desc; + } + return i18n( "body part" ); } QString mimeTypeForContent( KMime::Content *content ) { - if ( content->contentType( false ) ) - return QString::fromLatin1( content->contentType()->mimeType() ); - return QString(); + if ( content->contentType( false ) ) + return QString::fromLatin1( content->contentType()->mimeType() ); + return QString(); } QString typeForContent( KMime::Content *content ) { - if ( content->contentType( false ) ) - { - const QString contentMimeType = QString::fromLatin1(content->contentType()->mimeType()); - KMimeType::Ptr mimeType = KMimeType::mimeType( contentMimeType ); - if ( mimeType.isNull() ) - return contentMimeType; - return mimeType->comment(); - } - else - return QString(); + if ( content->contentType( false ) ) + { + const QString contentMimeType = QString::fromLatin1(content->contentType()->mimeType()); + KMimeType::Ptr mimeType = KMimeType::mimeType( contentMimeType ); + if ( mimeType.isNull() ) + return contentMimeType; + return mimeType->comment(); + } + else + return QString(); } QString sizeOfContent( KMime::Content *content ) { - if ( content->body().isEmpty() ) - return QString(); - return KGlobal::locale()->formatByteSize( content->body().size() ); + if ( content->body().isEmpty() ) + return QString(); + return KGlobal::locale()->formatByteSize( content->body().size() ); } KIcon iconForContent( KMime::Content *content ) { - if ( content->contentType( false ) ) - { - KMimeType::Ptr mimeType = KMimeType::mimeType( QString::fromLatin1( content->contentType()->mimeType() ) ); - if ( mimeType.isNull() || mimeType->name() == QLatin1String("application/octet-stream") ) { - const QString name = descriptionForContent(content); - mimeType = MessageViewer::Util::mimetype(name); + if ( content->contentType( false ) ) + { + KMimeType::Ptr mimeType = KMimeType::mimeType( QString::fromLatin1( content->contentType()->mimeType() ) ); + if ( mimeType.isNull() || mimeType->name() == QLatin1String("application/octet-stream") ) { + const QString name = descriptionForContent(content); + mimeType = MessageViewer::Util::mimetype(name); + } + if ( mimeType.isNull() || mimeType->iconName().isEmpty() ) + return KIcon(); + if( mimeType->name().startsWith( QLatin1String( "multipart/" ) ) ) + return KIcon( QLatin1String("folder") ); + return KIcon( mimeType->iconName() ); } - if ( mimeType.isNull() || mimeType->iconName().isEmpty() ) - return KIcon(); - if( mimeType->name().startsWith( QLatin1String( "multipart/" ) ) ) - return KIcon( QLatin1String("folder") ); - return KIcon( mimeType->iconName() ); - } - else - return KIcon(); + else + return KIcon(); } KMime::Content *root; @@ -128,129 +128,130 @@ MimeTreeModel::~MimeTreeModel() { - delete d; + delete d; } void MimeTreeModel::setRoot(KMime::Content * root) { - d->root = root; - reset(); + d->root = root; + reset(); } KMime::Content* MimeTreeModel::root() { - return d->root; + return d->root; } QModelIndex MimeTreeModel::index(int row, int column, const QModelIndex &parent) const { - if ( !parent.isValid() ) { - if ( row != 0 ) - return QModelIndex(); - return createIndex( row, column, d->root ); - } - - KMime::Content *parentContent = static_cast( parent.internalPointer() ); - if ( !parentContent || parentContent->contents().count() <= row || row < 0 ) - return QModelIndex(); - KMime::Content *content = parentContent->contents().at( row ); - return createIndex( row, column, content ); + if ( !parent.isValid() ) { + if ( row != 0 ) + return QModelIndex(); + return createIndex( row, column, d->root ); + } + + KMime::Content *parentContent = static_cast( parent.internalPointer() ); + if ( !parentContent || parentContent->contents().count() <= row || row < 0 ) + return QModelIndex(); + KMime::Content *content = parentContent->contents().at( row ); + return createIndex( row, column, content ); } QModelIndex MimeTreeModel::parent(const QModelIndex & index) const { - if ( !index.isValid() ) - return QModelIndex(); - KMime::Content *currentContent = static_cast( index.internalPointer() ); - if ( !currentContent ) - return QModelIndex(); - - KMime::ContentIndex currentIndex = d->root->indexForContent( currentContent ); - if ( !currentIndex.isValid() ) - return QModelIndex(); - d->contentIndexUp( currentIndex ); - KMime::Content *parentContent = d->root->content( currentIndex ); - int row = 0; - if ( currentIndex.isValid() ) - row = d->contentIndexUp( currentIndex ) - 1; // 1 based -> 0 based + if ( !index.isValid() ) + return QModelIndex(); + KMime::Content *currentContent = static_cast( index.internalPointer() ); + if ( !currentContent ) + return QModelIndex(); + + KMime::ContentIndex currentIndex = d->root->indexForContent( currentContent ); + if ( !currentIndex.isValid() ) + return QModelIndex(); + d->contentIndexUp( currentIndex ); + KMime::Content *parentContent = d->root->content( currentIndex ); + int row = 0; + if ( currentIndex.isValid() ) + row = d->contentIndexUp( currentIndex ) - 1; // 1 based -> 0 based - return createIndex( row, 0, parentContent ); + return createIndex( row, 0, parentContent ); } int MimeTreeModel::rowCount(const QModelIndex & parent) const { - if ( !d->root ) + if ( !d->root ) + return 0; + if ( !parent.isValid() ) + return 1; + KMime::Content *parentContent = static_cast( parent.internalPointer() ); + if ( parentContent ) + return parentContent->contents().count(); return 0; - if ( !parent.isValid() ) - return 1; - KMime::Content *parentContent = static_cast( parent.internalPointer() ); - if ( parentContent ) - return parentContent->contents().count(); - return 0; } int MimeTreeModel::columnCount(const QModelIndex & parent) const { - Q_UNUSED( parent ); - return 3; + Q_UNUSED( parent ); + return 3; } QVariant MimeTreeModel::data(const QModelIndex & index, int role) const { - KMime::Content *content = static_cast( index.internalPointer() ); - if ( !content ) + KMime::Content *content = static_cast( index.internalPointer() ); + if ( !content ) + return QVariant(); + if ( role == Qt::ToolTipRole ) { + // TODO + //return d->root->indexForContent( content ).toString(); + return QVariant(); + } + if ( role == Qt::DisplayRole ) { + switch( index.column() ) { + case 0: + return d->descriptionForContent( content ); + case 1: + return d->typeForContent( content ); + case 2: + return d->sizeOfContent( content ); + } + } + if ( role == Qt::DecorationRole && index.column() == 0 ) { + return d->iconForContent( content ); + } + if ( role == ContentIndexRole ) + return QVariant::fromValue( d->root->indexForContent( content ) ); + if ( role == ContentRole ) + return QVariant::fromValue( content ); + if ( role == MimeTypeRole ) + return d->mimeTypeForContent( content ); + if ( role == MainBodyPartRole ) { + KMime::Message* topLevelMsg = dynamic_cast( d->root ); + if ( !topLevelMsg ) + return false; + return topLevelMsg->mainBodyPart() == content; + } + if ( role == AlternativeBodyPartRole ) { + KMime::Message* topLevelMsg = dynamic_cast( d->root ); + if ( !topLevelMsg ) + return false; + return topLevelMsg->mainBodyPart( content->contentType()->mimeType() ) == content; + } return QVariant(); - if ( role == Qt::ToolTipRole ) { - // TODO - //return d->root->indexForContent( content ).toString(); - } - if ( role == Qt::DisplayRole ) { - switch( index.column() ) { - case 0: - return d->descriptionForContent( content ); - case 1: - return d->typeForContent( content ); - case 2: - return d->sizeOfContent( content ); - } - } - if ( role == Qt::DecorationRole && index.column() == 0 ) { - return d->iconForContent( content ); - } - if ( role == ContentIndexRole ) - return QVariant::fromValue( d->root->indexForContent( content ) ); - if ( role == ContentRole ) - return QVariant::fromValue( content ); - if ( role == MimeTypeRole ) - return d->mimeTypeForContent( content ); - if ( role == MainBodyPartRole ) { - KMime::Message* topLevelMsg = dynamic_cast( d->root ); - if ( !topLevelMsg ) - return false; - return topLevelMsg->mainBodyPart() == content; - } - if ( role == AlternativeBodyPartRole ) { - KMime::Message* topLevelMsg = dynamic_cast( d->root ); - if ( !topLevelMsg ) - return false; - return topLevelMsg->mainBodyPart( content->contentType()->mimeType() ) == content; - } - return QVariant(); } QVariant MimeTreeModel::headerData(int section, Qt::Orientation orientation, int role) const { - if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) { - switch ( section ) { - case 0: - return i18n( "Description" ); - case 1: - return i18n( "Type" ); - case 2: - return i18n( "Size" ); + if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) { + switch ( section ) { + case 0: + return i18n( "Description" ); + case 1: + return i18n( "Type" ); + case 2: + return i18n( "Size" ); + } } - } - return QAbstractItemModel::headerData( section, orientation, role ); + return QAbstractItemModel::headerData( section, orientation, role ); } diff -Nru kdepim-4.12.97/messageviewer/viewer/mimetreemodel.h kdepim-4.13.0/messageviewer/viewer/mimetreemodel.h --- kdepim-4.12.97/messageviewer/viewer/mimetreemodel.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/mimetreemodel.h 2014-04-10 07:40:20.000000000 +0000 @@ -23,7 +23,7 @@ #include namespace KMime { - class Content; +class Content; } namespace MessageViewer { @@ -33,16 +33,16 @@ */ class MimeTreeModel : public QAbstractItemModel { - Q_OBJECT + Q_OBJECT - public: +public: enum Role { - ContentIndexRole = Qt::UserRole + 1, - ContentRole, - MimeTypeRole, - MainBodyPartRole, - AlternativeBodyPartRole, - UserRole = Qt::UserRole + 100 + ContentIndexRole = Qt::UserRole + 1, + ContentRole, + MimeTypeRole, + MainBodyPartRole, + AlternativeBodyPartRole, + UserRole = Qt::UserRole + 100 }; explicit MimeTreeModel( QObject *parent = 0 ); ~MimeTreeModel(); @@ -58,7 +58,7 @@ QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; - private: +private: class Private; Private* const d; }; diff -Nru kdepim-4.12.97/messageviewer/viewer/objecttreeemptysource.cpp kdepim-4.13.0/messageviewer/viewer/objecttreeemptysource.cpp --- kdepim-4.12.97/messageviewer/viewer/objecttreeemptysource.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/objecttreeemptysource.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -28,7 +28,7 @@ EmptySource::EmptySource() : ObjectTreeSourceIf() { - mAllowDecryption = false; + mAllowDecryption = false; } EmptySource::~EmptySource() @@ -37,68 +37,68 @@ bool EmptySource::htmlMail() { - return true; + return true; } bool EmptySource::decryptMessage() { - return mAllowDecryption; + return mAllowDecryption; } bool EmptySource::htmlLoadExternal() { - return false; + return false; } bool EmptySource::showSignatureDetails() { - return false; + return false; } void EmptySource::setHtmlMode( Util::HtmlMode mode ) { - Q_UNUSED( mode ); + Q_UNUSED( mode ); } void EmptySource::setAllowDecryption( bool allowDecryption ) { - mAllowDecryption = allowDecryption; + mAllowDecryption = allowDecryption; } int EmptySource::levelQuote() { - return 1; + return 1; } const QTextCodec * EmptySource::overrideCodec() { - return 0; + return 0; } QString EmptySource::createMessageHeader( KMime::Message *message ) { - Q_UNUSED( message ); - return QString(); //do nothing + Q_UNUSED( message ); + return QString(); //do nothing } QObject *EmptySource::sourceObject() { - return 0; + return 0; } const AttachmentStrategy * EmptySource::attachmentStrategy() { - return AttachmentStrategy::smart(); + return AttachmentStrategy::smart(); } HtmlWriter * EmptySource::htmlWriter() { - return 0; + return 0; } CSSHelper* EmptySource::cssHelper() { - return 0; + return 0; } } diff -Nru kdepim-4.12.97/messageviewer/viewer/objecttreeemptysource.h kdepim-4.13.0/messageviewer/viewer/objecttreeemptysource.h --- kdepim-4.12.97/messageviewer/viewer/objecttreeemptysource.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/objecttreeemptysource.h 2014-04-10 07:40:20.000000000 +0000 @@ -29,25 +29,25 @@ /** An ObjectTreeSource that does not work on anything */ class MESSAGEVIEWER_EXPORT EmptySource : public ObjectTreeSourceIf { - public: - EmptySource( ); - ~EmptySource(); - bool htmlMail(); - bool decryptMessage(); - bool htmlLoadExternal(); - bool showSignatureDetails(); - void setHtmlMode( MessageViewer::Util::HtmlMode mode ); - void setAllowDecryption( bool allowDecryption ); - int levelQuote(); - const QTextCodec * overrideCodec(); - QString createMessageHeader( KMime::Message *message ); - const AttachmentStrategy * attachmentStrategy(); - HtmlWriter * htmlWriter(); - CSSHelper* cssHelper(); - QObject *sourceObject(); +public: + EmptySource( ); + ~EmptySource(); + bool htmlMail(); + bool decryptMessage(); + bool htmlLoadExternal(); + bool showSignatureDetails(); + void setHtmlMode( MessageViewer::Util::HtmlMode mode ); + void setAllowDecryption( bool allowDecryption ); + int levelQuote(); + const QTextCodec * overrideCodec(); + QString createMessageHeader( KMime::Message *message ); + const AttachmentStrategy * attachmentStrategy(); + HtmlWriter * htmlWriter(); + CSSHelper* cssHelper(); + QObject *sourceObject(); private: - bool mAllowDecryption; + bool mAllowDecryption; }; } diff -Nru kdepim-4.12.97/messageviewer/viewer/objecttreeparser.cpp kdepim-4.13.0/messageviewer/viewer/objecttreeparser.cpp --- kdepim-4.12.97/messageviewer/viewer/objecttreeparser.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/objecttreeparser.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -126,39 +126,39 @@ // A small class that eases temporary CryptPlugWrapper changes: class ObjectTreeParser::CryptoProtocolSaver { - ObjectTreeParser * otp; - const Kleo::CryptoBackend::Protocol * protocol; + ObjectTreeParser * otp; + const Kleo::CryptoBackend::Protocol * protocol; public: - CryptoProtocolSaver( ObjectTreeParser * _otp, const Kleo::CryptoBackend::Protocol* _w ) - : otp( _otp ), protocol( _otp ? _otp->cryptoProtocol() : 0 ) - { - if ( otp ) - otp->setCryptoProtocol( _w ); - } + CryptoProtocolSaver( ObjectTreeParser * _otp, const Kleo::CryptoBackend::Protocol* _w ) + : otp( _otp ), protocol( _otp ? _otp->cryptoProtocol() : 0 ) + { + if ( otp ) + otp->setCryptoProtocol( _w ); + } - ~CryptoProtocolSaver() { - if ( otp ) - otp->setCryptoProtocol( protocol ); - } + ~CryptoProtocolSaver() { + if ( otp ) + otp->setCryptoProtocol( protocol ); + } }; ObjectTreeParser::ObjectTreeParser( const ObjectTreeParser *topLevelParser, bool showOnlyOneMimePart, bool keepEncryptions, bool includeSignatures, const AttachmentStrategy * strategy ) - : mSource( topLevelParser->mSource ), - mNodeHelper( topLevelParser->mNodeHelper ), - mTopLevelContent( topLevelParser->mTopLevelContent ), - mCryptoProtocol( topLevelParser->mCryptoProtocol ), - mShowOnlyOneMimePart( showOnlyOneMimePart ), - mKeepEncryptions( keepEncryptions ), - mIncludeSignatures( includeSignatures ), - mHasPendingAsyncJobs( false ), - mAllowAsync( topLevelParser->mAllowAsync ), - mShowRawToltecMail( false ), - mAttachmentStrategy( strategy ) + : mSource( topLevelParser->mSource ), + mNodeHelper( topLevelParser->mNodeHelper ), + mTopLevelContent( topLevelParser->mTopLevelContent ), + mCryptoProtocol( topLevelParser->mCryptoProtocol ), + mShowOnlyOneMimePart( showOnlyOneMimePart ), + mKeepEncryptions( keepEncryptions ), + mIncludeSignatures( includeSignatures ), + mHasPendingAsyncJobs( false ), + mAllowAsync( topLevelParser->mAllowAsync ), + mShowRawToltecMail( false ), + mAttachmentStrategy( strategy ) { - init(); + init(); } ObjectTreeParser::ObjectTreeParser( ObjectTreeSourceIf *source, @@ -167,94 +167,94 @@ bool showOnlyOneMimePart, bool keepEncryptions, bool includeSignatures, const AttachmentStrategy * strategy ) - : mSource( source ), - mNodeHelper( nodeHelper ), - mTopLevelContent( 0 ), - mCryptoProtocol( protocol ), - mShowOnlyOneMimePart( showOnlyOneMimePart ), - mKeepEncryptions( keepEncryptions ), - mIncludeSignatures( includeSignatures ), - mHasPendingAsyncJobs( false ), - mAllowAsync( false ), - mShowRawToltecMail( false ), - mAttachmentStrategy( strategy ) + : mSource( source ), + mNodeHelper( nodeHelper ), + mTopLevelContent( 0 ), + mCryptoProtocol( protocol ), + mShowOnlyOneMimePart( showOnlyOneMimePart ), + mKeepEncryptions( keepEncryptions ), + mIncludeSignatures( includeSignatures ), + mHasPendingAsyncJobs( false ), + mAllowAsync( false ), + mShowRawToltecMail( false ), + mAttachmentStrategy( strategy ) { - init(); + init(); } void ObjectTreeParser::init() { - assert( mSource ); - if ( !attachmentStrategy() ) - mAttachmentStrategy = mSource->attachmentStrategy(); - - if ( !mNodeHelper ) { - mNodeHelper = new NodeHelper(); - mDeleteNodeHelper = true; - } else { - mDeleteNodeHelper = false; - } + assert( mSource ); + if ( !attachmentStrategy() ) + mAttachmentStrategy = mSource->attachmentStrategy(); + + if ( !mNodeHelper ) { + mNodeHelper = new NodeHelper(); + mDeleteNodeHelper = true; + } else { + mDeleteNodeHelper = false; + } } ObjectTreeParser::ObjectTreeParser( const ObjectTreeParser & other ) - : mSource( other.mSource ), - mNodeHelper( other.nodeHelper() ), //TODO(Andras) hm, review what happens if mDeleteNodeHelper was true in the source - mTopLevelContent( other.mTopLevelContent ), - mCryptoProtocol( other.cryptoProtocol() ), - mShowOnlyOneMimePart( other.showOnlyOneMimePart() ), - mKeepEncryptions( other.keepEncryptions() ), - mIncludeSignatures( other.includeSignatures() ), - mHasPendingAsyncJobs( other.hasPendingAsyncJobs() ), - mAllowAsync( other.allowAsync() ), - mAttachmentStrategy( other.attachmentStrategy() ), - mDeleteNodeHelper( false ) // TODO see above + : mSource( other.mSource ), + mNodeHelper( other.nodeHelper() ), //TODO(Andras) hm, review what happens if mDeleteNodeHelper was true in the source + mTopLevelContent( other.mTopLevelContent ), + mCryptoProtocol( other.cryptoProtocol() ), + mShowOnlyOneMimePart( other.showOnlyOneMimePart() ), + mKeepEncryptions( other.keepEncryptions() ), + mIncludeSignatures( other.includeSignatures() ), + mHasPendingAsyncJobs( other.hasPendingAsyncJobs() ), + mAllowAsync( other.allowAsync() ), + mAttachmentStrategy( other.attachmentStrategy() ), + mDeleteNodeHelper( false ) // TODO see above { } ObjectTreeParser::~ObjectTreeParser() { - if ( mDeleteNodeHelper ) { - delete mNodeHelper; - mNodeHelper = 0; - } + if ( mDeleteNodeHelper ) { + delete mNodeHelper; + mNodeHelper = 0; + } } void ObjectTreeParser::copyContentFrom( const ObjectTreeParser *other ) { - mRawDecryptedBody += other->rawDecryptedBody(); - mPlainTextContent += other->plainTextContent(); - mHtmlContent += other->htmlContent(); - if ( !other->plainTextContentCharset().isEmpty() ) { - mPlainTextContentCharset = other->plainTextContentCharset(); - } - if ( !other->htmlContentCharset().isEmpty() ) { - mHtmlContentCharset = other->htmlContentCharset(); - } + mRawDecryptedBody += other->rawDecryptedBody(); + mPlainTextContent += other->plainTextContent(); + mHtmlContent += other->htmlContent(); + if ( !other->plainTextContentCharset().isEmpty() ) { + mPlainTextContentCharset = other->plainTextContentCharset(); + } + if ( !other->htmlContentCharset().isEmpty() ) { + mHtmlContentCharset = other->htmlContentCharset(); + } } void ObjectTreeParser::createAndParseTempNode( KMime::Content* parentNode, const char* content, const char* cntDesc ) { -// kDebug() << "CONTENT: " << QByteArray( content ).left( 100 ) << " CNTDESC: " << cntDesc; + // kDebug() << "CONTENT: " << QByteArray( content ).left( 100 ) << " CNTDESC: " << cntDesc; - KMime::Content *newNode = new KMime::Content(); - newNode->setContent( KMime::CRLFtoLF( content ) ); - newNode->parse(); -/* + KMime::Content *newNode = new KMime::Content(); + newNode->setContent( KMime::CRLFtoLF( content ) ); + newNode->parse(); + /* kDebug() << "MEDIATYPE: " << newNode->contentType()->mediaType() << newNode->contentType()->mimeType() ; kDebug() << "DECODEDCONTENT: " << newNode->decodedContent().left(400); kDebug() << "ENCODEDCONTENT: " << newNode->encodedContent().left(400); kDebug() << "BODY: " << newNode->body().left(400); */ - if ( !newNode->head().isEmpty() ) { - newNode->contentDescription()->from7BitString( cntDesc ); - } - mNodeHelper->attachExtraContent( parentNode, newNode ); + if ( !newNode->head().isEmpty() ) { + newNode->contentDescription()->from7BitString( cntDesc ); + } + mNodeHelper->attachExtraContent( parentNode, newNode ); - ObjectTreeParser otp( this ); - otp.parseObjectTreeInternal( newNode ); - copyContentFrom( &otp ); + ObjectTreeParser otp( this ); + otp.parseObjectTreeInternal( newNode ); + copyContentFrom( &otp ); } @@ -262,196 +262,196 @@ void ObjectTreeParser::parseObjectTree( KMime::Content * node ) { - mTopLevelContent = node; - parseObjectTreeInternal( node ); + mTopLevelContent = node; + parseObjectTreeInternal( node ); } void ObjectTreeParser::parseObjectTreeInternal( KMime::Content * node ) { - if ( !node ) - return; + if ( !node ) + return; - // reset pending async jobs state (we'll rediscover pending jobs as we go) - mHasPendingAsyncJobs = false; + // reset pending async jobs state (we'll rediscover pending jobs as we go) + mHasPendingAsyncJobs = false; - // reset "processed" flags for... - if ( showOnlyOneMimePart() ) { - // ... this node and all descendants - mNodeHelper->setNodeUnprocessed( node, false ); - if ( MessageCore::NodeHelper::firstChild( node ) ) { - mNodeHelper->setNodeUnprocessed( node, true ); - } - } else if ( !node->parent() ) { - // ...this node and all it's siblings and descendants - mNodeHelper->setNodeUnprocessed( node, true ); - } + // reset "processed" flags for... + if ( showOnlyOneMimePart() ) { + // ... this node and all descendants + mNodeHelper->setNodeUnprocessed( node, false ); + if ( MessageCore::NodeHelper::firstChild( node ) ) { + mNodeHelper->setNodeUnprocessed( node, true ); + } + } else if ( !node->parent() ) { + // ...this node and all it's siblings and descendants + mNodeHelper->setNodeUnprocessed( node, true ); + } - // Make sure the whole content is relative, so that nothing is painted over the header - // if a malicious message uses absolute positioning. - // Also force word wrapping, which is useful for printing, see https://issues.kolab.org/issue3992. - bool isRoot = node->isTopLevel(); - if ( isRoot && htmlWriter() ) - htmlWriter()->queue( QLatin1String("
\n") ); - - for( ; node ; node = MessageCore::NodeHelper::nextSibling( node ) ) - { - if ( mNodeHelper->nodeProcessed( node ) ) { - continue; - } - - ProcessResult processResult( mNodeHelper ); - - KMime::ContentIndex contentIndex = node->index(); - if ( htmlWriter() /*&& contentIndex.isValid()*/ ) - htmlWriter()->queue( QString::fromLatin1("").arg( contentIndex.toString() ) ); - - QByteArray mediaType( "text" ); - QByteArray subType( "plain" ); - if ( node->contentType( false ) && !node->contentType()->mediaType().isEmpty() && - !node->contentType()->subType().isEmpty() ) { - mediaType = node->contentType()->mediaType(); - subType = node->contentType()->subType(); - } - - // First, try if an external plugin can handle this MIME part - if ( const Interface::BodyPartFormatter * formatter - = BodyPartFormatterFactory::instance()->createFor( mediaType, subType ) ) { - PartNodeBodyPart part( mTopLevelContent, node, mNodeHelper, codecFor( node ) ); - // Set the default display strategy for this body part relying on the - // identity of Interface::BodyPart::Display and AttachmentStrategy::Display - part.setDefaultDisplay( (Interface::BodyPart::Display) attachmentStrategy()->defaultDisplay( node ) ); - - writeAttachmentMarkHeader( node ); - mNodeHelper->setNodeDisplayedEmbedded( node, true ); - - QObject * asyncResultObserver = allowAsync() ? mSource->sourceObject() : 0; - const Interface::BodyPartFormatter::Result result = formatter->format( &part, htmlWriter(), asyncResultObserver ); - switch ( result ) { - case Interface::BodyPartFormatter::AsIcon: - processResult.setNeverDisplayInline( true ); - mNodeHelper->setNodeDisplayedEmbedded( node, false ); - // fall through: - case Interface::BodyPartFormatter::Failed: - defaultHandling( node, processResult ); - break; - case Interface::BodyPartFormatter::Ok: - case Interface::BodyPartFormatter::NeedContent: - // FIXME: incomplete content handling - ; - } + // Make sure the whole content is relative, so that nothing is painted over the header + // if a malicious message uses absolute positioning. + // Also force word wrapping, which is useful for printing, see https://issues.kolab.org/issue3992. + bool isRoot = node->isTopLevel(); + if ( isRoot && htmlWriter() ) + htmlWriter()->queue( QLatin1String("
\n") ); - writeAttachmentMarkFooter(); + for( ; node ; node = MessageCore::NodeHelper::nextSibling( node ) ) + { + if ( mNodeHelper->nodeProcessed( node ) ) { + continue; + } - // No external plugin can handle the MIME part, handle it internally - } else { - const BodyPartFormatter * bpf - = BodyPartFormatter::createFor( mediaType, subType ); - if ( !bpf ) { - kFatal() << "THIS SHOULD NO LONGER HAPPEN:" << mediaType << '/' << subType; - } - writeAttachmentMarkHeader( node ); - if ( bpf && !bpf->process( this, node, processResult ) ) { - defaultHandling( node, processResult ); - } - writeAttachmentMarkFooter(); - } - mNodeHelper->setNodeProcessed( node, false); + ProcessResult processResult( mNodeHelper ); - // adjust signed/encrypted flags if inline PGP was found - processResult.adjustCryptoStatesOfNode( node ); + KMime::ContentIndex contentIndex = node->index(); + if ( htmlWriter() /*&& contentIndex.isValid()*/ ) + htmlWriter()->queue( QString::fromLatin1("").arg( contentIndex.toString() ) ); + + QByteArray mediaType( "text" ); + QByteArray subType( "plain" ); + if ( node->contentType( false ) && !node->contentType()->mediaType().isEmpty() && + !node->contentType()->subType().isEmpty() ) { + mediaType = node->contentType()->mediaType(); + subType = node->contentType()->subType(); + } - if ( showOnlyOneMimePart() ) - break; - } + // First, try if an external plugin can handle this MIME part + if ( const Interface::BodyPartFormatter * formatter + = BodyPartFormatterFactory::instance()->createFor( mediaType, subType ) ) { + PartNodeBodyPart part( mTopLevelContent, node, mNodeHelper, codecFor( node ) ); + // Set the default display strategy for this body part relying on the + // identity of Interface::BodyPart::Display and AttachmentStrategy::Display + part.setDefaultDisplay( (Interface::BodyPart::Display) attachmentStrategy()->defaultDisplay( node ) ); + + writeAttachmentMarkHeader( node ); + mNodeHelper->setNodeDisplayedEmbedded( node, true ); + + QObject * asyncResultObserver = allowAsync() ? mSource->sourceObject() : 0; + const Interface::BodyPartFormatter::Result result = formatter->format( &part, htmlWriter(), asyncResultObserver ); + switch ( result ) { + case Interface::BodyPartFormatter::AsIcon: + processResult.setNeverDisplayInline( true ); + mNodeHelper->setNodeDisplayedEmbedded( node, false ); + // fall through: + case Interface::BodyPartFormatter::Failed: + defaultHandling( node, processResult ); + break; + case Interface::BodyPartFormatter::Ok: + case Interface::BodyPartFormatter::NeedContent: + // FIXME: incomplete content handling + ; + } - if ( isRoot && htmlWriter() ) - htmlWriter()->queue( QLatin1String("
\n") ); -} + writeAttachmentMarkFooter(); -void ObjectTreeParser::defaultHandling( KMime::Content * node, ProcessResult & result ) { - // ### (mmutz) default handling should go into the respective - // ### bodypartformatters. - if ( !htmlWriter() ) { - kWarning() << "no htmlWriter()"; - return; - } + // No external plugin can handle the MIME part, handle it internally + } else { + const BodyPartFormatter * bpf + = BodyPartFormatter::createFor( mediaType, subType ); + if ( !bpf ) { + kFatal() << "THIS SHOULD NO LONGER HAPPEN:" << mediaType << '/' << subType; + } + writeAttachmentMarkHeader( node ); + if ( bpf && !bpf->process( this, node, processResult ) ) { + defaultHandling( node, processResult ); + } + writeAttachmentMarkFooter(); + } + mNodeHelper->setNodeProcessed( node, false); - // always show images in multipart/related when showing in html, not with an additional icon - if ( result.isImage() && node->parent() && - node->parent()->contentType()->subType() == "related" && mSource->htmlMail() && !showOnlyOneMimePart() ) { - QString fileName = mNodeHelper->writeNodeToTempFile( node ); - QString href = QLatin1String("file:///") + fileName; - QByteArray cid = node->contentID()->identifier(); - htmlWriter()->embedPart( cid, href ); - nodeHelper()->setNodeDisplayedEmbedded( node, true ); - return; - } + // adjust signed/encrypted flags if inline PGP was found + processResult.adjustCryptoStatesOfNode( node ); - if ( node->contentType()->mimeType() == QByteArray( "application/octet-stream" ) && - ( node->contentType()->name().endsWith( QString::fromLatin1( "p7m" ) ) || - node->contentType()->name().endsWith( QString::fromLatin1( "p7s" ) ) || - node->contentType()->name().endsWith( QString::fromLatin1( "p7c" ) ) - ) && - processApplicationPkcs7MimeSubtype( node, result ) ) { - return; - } + if ( showOnlyOneMimePart() ) + break; + } - const AttachmentStrategy *const as = attachmentStrategy(); - if ( as && as->defaultDisplay( node ) == AttachmentStrategy::None && - !showOnlyOneMimePart() && - node->parent() /* message is not an attachment */ ) { - mNodeHelper->setNodeDisplayedHidden( node, true ); - return; - } + if ( isRoot && htmlWriter() ) + htmlWriter()->queue( QLatin1String("
\n") ); +} - bool asIcon = true; - if ( !result.neverDisplayInline() ) - if ( as ) - asIcon = as->defaultDisplay( node ) == AttachmentStrategy::AsIcon; - - // Show it inline if showOnlyOneMimePart(), which means the user clicked the image - // in the message structure viewer manually, and therefore wants to see the full image - if ( result.isImage() && showOnlyOneMimePart() && !result.neverDisplayInline() ) - asIcon = false; - - // neither image nor text -> show as icon - if ( !result.isImage() - && !node->contentType()->isText() ) - asIcon = true; +void ObjectTreeParser::defaultHandling( KMime::Content * node, ProcessResult & result ) { + // ### (mmutz) default handling should go into the respective + // ### bodypartformatters. + if ( !htmlWriter() ) { + kWarning() << "no htmlWriter()"; + return; + } + + // always show images in multipart/related when showing in html, not with an additional icon + if ( result.isImage() && node->parent() && + node->parent()->contentType()->subType() == "related" && mSource->htmlMail() && !showOnlyOneMimePart() ) { + QString fileName = mNodeHelper->writeNodeToTempFile( node ); + QString href = QLatin1String("file:///") + fileName; + QByteArray cid = node->contentID()->identifier(); + htmlWriter()->embedPart( cid, href ); + nodeHelper()->setNodeDisplayedEmbedded( node, true ); + return; + } + + if ( node->contentType()->mimeType() == QByteArray( "application/octet-stream" ) && + ( node->contentType()->name().endsWith( QString::fromLatin1( "p7m" ) ) || + node->contentType()->name().endsWith( QString::fromLatin1( "p7s" ) ) || + node->contentType()->name().endsWith( QString::fromLatin1( "p7c" ) ) + ) && + processApplicationPkcs7MimeSubtype( node, result ) ) { + return; + } + + const AttachmentStrategy *const as = attachmentStrategy(); + if ( as && as->defaultDisplay( node ) == AttachmentStrategy::None && + !showOnlyOneMimePart() && + node->parent() /* message is not an attachment */ ) { + mNodeHelper->setNodeDisplayedHidden( node, true ); + return; + } + + bool asIcon = true; + if ( !result.neverDisplayInline() ) + if ( as ) + asIcon = as->defaultDisplay( node ) == AttachmentStrategy::AsIcon; + + // Show it inline if showOnlyOneMimePart(), which means the user clicked the image + // in the message structure viewer manually, and therefore wants to see the full image + if ( result.isImage() && showOnlyOneMimePart() && !result.neverDisplayInline() ) + asIcon = false; + + // neither image nor text -> show as icon + if ( !result.isImage() + && !node->contentType()->isText() ) + asIcon = true; -/*FIXME(Andras) port it + /*FIXME(Andras) port it // if the image is not complete do not try to show it inline if ( result.isImage() && !node->msgPart().isComplete() ) asIcon = true; */ - if ( asIcon ) { - if ( !( as && as->defaultDisplay( node ) == AttachmentStrategy::None ) || - showOnlyOneMimePart() ) { - // Write the node as icon only - writePartIcon( node ); + if ( asIcon ) { + if ( !( as && as->defaultDisplay( node ) == AttachmentStrategy::None ) || + showOnlyOneMimePart() ) { + // Write the node as icon only + writePartIcon( node ); + } else { + mNodeHelper->setNodeDisplayedHidden( node, true ); + } + } else if ( result.isImage() ) { + // Embed the image + mNodeHelper->setNodeDisplayedEmbedded( node, true ); + writePartIcon( node, true ); } else { - mNodeHelper->setNodeDisplayedHidden( node, true ); + mNodeHelper->setNodeDisplayedEmbedded( node, true ); + writeBodyString( node->decodedContent(), + NodeHelper::fromAsString( node ), + codecFor( node ), result, false ); } - } else if ( result.isImage() ) { - // Embed the image - mNodeHelper->setNodeDisplayedEmbedded( node, true ); - writePartIcon( node, true ); - } else { - mNodeHelper->setNodeDisplayedEmbedded( node, true ); - writeBodyString( node->decodedContent(), - NodeHelper::fromAsString( node ), - codecFor( node ), result, false ); - } - // end of ### + // end of ### } void ProcessResult::adjustCryptoStatesOfNode( KMime::Content * node ) const { - if ( ( inlineSignatureState() != KMMsgNotSigned ) || - ( inlineEncryptionState() != KMMsgNotEncrypted ) ) { - mNodeHelper->setSignatureState( node, inlineSignatureState() ); - mNodeHelper->setEncryptionState( node, inlineEncryptionState() ); - } + if ( ( inlineSignatureState() != KMMsgNotSigned ) || + ( inlineEncryptionState() != KMMsgNotEncrypted ) ) { + mNodeHelper->setSignatureState( node, inlineSignatureState() ); + mNodeHelper->setEncryptionState( node, inlineEncryptionState() ); + } } ////////////////// @@ -460,22 +460,22 @@ static int signatureToStatus( const GpgME::Signature &sig ) { - switch ( sig.status().code() ) { + switch ( sig.status().code() ) { case GPG_ERR_NO_ERROR: - return GPGME_SIG_STAT_GOOD; + return GPGME_SIG_STAT_GOOD; case GPG_ERR_BAD_SIGNATURE: - return GPGME_SIG_STAT_BAD; + return GPGME_SIG_STAT_BAD; case GPG_ERR_NO_PUBKEY: - return GPGME_SIG_STAT_NOKEY; + return GPGME_SIG_STAT_NOKEY; case GPG_ERR_NO_DATA: - return GPGME_SIG_STAT_NOSIG; + return GPGME_SIG_STAT_NOSIG; case GPG_ERR_SIG_EXPIRED: - return GPGME_SIG_STAT_GOOD_EXP; + return GPGME_SIG_STAT_GOOD_EXP; case GPG_ERR_KEY_EXPIRED: - return GPGME_SIG_STAT_GOOD_EXPKEY; + return GPGME_SIG_STAT_GOOD_EXPKEY; default: - return GPGME_SIG_STAT_ERROR; - } + return GPGME_SIG_STAT_ERROR; + } } bool ObjectTreeParser::writeOpaqueOrMultipartSignedData( KMime::Content* data, @@ -486,451 +486,451 @@ const std::vector & paramSignatures, bool hideErrors ) { -// kDebug() << "DECRYPT" << data; - bool bIsOpaqueSigned = false; - enum { NO_PLUGIN, NOT_INITIALIZED, CANT_VERIFY_SIGNATURES } - cryptPlugError = NO_PLUGIN; - - const Kleo::CryptoBackend::Protocol* cryptProto = cryptoProtocol(); - - QString cryptPlugLibName; - QString cryptPlugDisplayName; - if ( cryptProto ) { - cryptPlugLibName = cryptProto->name(); - cryptPlugDisplayName = cryptProto->displayName(); - } + // kDebug() << "DECRYPT" << data; + bool bIsOpaqueSigned = false; + enum { NO_PLUGIN, NOT_INITIALIZED, CANT_VERIFY_SIGNATURES } + cryptPlugError = NO_PLUGIN; + + const Kleo::CryptoBackend::Protocol* cryptProto = cryptoProtocol(); + + QString cryptPlugLibName; + QString cryptPlugDisplayName; + if ( cryptProto ) { + cryptPlugLibName = cryptProto->name(); + cryptPlugDisplayName = cryptProto->displayName(); + } #ifdef DEBUG_SIGNATURE #ifndef NDEBUG - if ( !doCheck ) - kDebug() << "showing OpenPGP (Encrypted+Signed) data"; - else - if ( data ) - kDebug() << "processing Multipart Signed data"; + if ( !doCheck ) + kDebug() << "showing OpenPGP (Encrypted+Signed) data"; else - kDebug() << "processing Opaque Signed data"; + if ( data ) + kDebug() << "processing Multipart Signed data"; + else + kDebug() << "processing Opaque Signed data"; #endif - if ( doCheck && cryptProto ) { - //kDebug() << "going to call CRYPTPLUG" << cryptPlugLibName; - } + if ( doCheck && cryptProto ) { + //kDebug() << "going to call CRYPTPLUG" << cryptPlugLibName; + } #endif - QByteArray cleartext; - QByteArray signaturetext; + QByteArray cleartext; + QByteArray signaturetext; - if ( doCheck && cryptProto ) { - if ( data ) { - cleartext = data->encodedContent(); + if ( doCheck && cryptProto ) { + if ( data ) { + cleartext = data->encodedContent(); #ifdef DEBUG_SIGNATURE - kDebug() << "ClearText : " << cleartext; + kDebug() << "ClearText : " << cleartext; - dumpToFile( "dat_01_reader_signedtext_before_canonicalization", - cleartext.data(), cleartext.length() ); + dumpToFile( "dat_01_reader_signedtext_before_canonicalization", + cleartext.data(), cleartext.length() ); - // replace simple LFs by CRLSs - // according to RfC 2633, 3.1.1 Canonicalization - kDebug() << "Converting LF to CRLF (see RfC 2633, 3.1.1 Canonicalization)"; + // replace simple LFs by CRLSs + // according to RfC 2633, 3.1.1 Canonicalization + kDebug() << "Converting LF to CRLF (see RfC 2633, 3.1.1 Canonicalization)"; #endif - cleartext = KMime::LFtoCRLF( cleartext ); + cleartext = KMime::LFtoCRLF( cleartext ); #ifdef DEBUG_SIGNATURE - kDebug() << " done."; + kDebug() << " done."; #endif -} - - dumpToFile( "dat_02_reader_signedtext_after_canonicalization", - cleartext.data(), cleartext.length() ); - - signaturetext = sign.decodedContent(); - dumpToFile( "dat_03_reader.sig", signaturetext.data(), - signaturetext.size() ); - } + } - std::vector signatures; - if ( !doCheck ) - signatures = paramSignatures; + dumpToFile( "dat_02_reader_signedtext_after_canonicalization", + cleartext.data(), cleartext.length() ); - PartMetaData messagePart; - messagePart.isSigned = true; - messagePart.technicalProblem = ( cryptProto == 0 ); - messagePart.isGoodSignature = false; - messagePart.isEncrypted = false; - messagePart.isDecryptable = false; - messagePart.keyTrust = Kpgp::KPGP_VALIDITY_UNKNOWN; - messagePart.status = i18n("Wrong Crypto Plug-In."); - messagePart.status_code = GPGME_SIG_STAT_NONE; + signaturetext = sign.decodedContent(); + dumpToFile( "dat_03_reader.sig", signaturetext.data(), + signaturetext.size() ); + } - GpgME::Key key; + std::vector signatures; + if ( !doCheck ) + signatures = paramSignatures; - if ( doCheck && cryptProto ) { -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: doCheck and cryptProto"; -#endif - GpgME::VerificationResult result; - if ( data ) { // detached -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: is detached signature"; -#endif - const VerifyDetachedBodyPartMemento * m - = dynamic_cast( mNodeHelper->bodyPartMemento( &sign, "verifydetached" ) ); - if ( !m ) { -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: no memento available"; -#endif - Kleo::VerifyDetachedJob * job = cryptProto->verifyDetachedJob(); - if ( !job ) { - cryptPlugError = CANT_VERIFY_SIGNATURES; - // PENDING(marc) cryptProto = 0 here? - } else { - QByteArray plainData = cleartext; - VerifyDetachedBodyPartMemento * newM - = new VerifyDetachedBodyPartMemento( job, cryptProto->keyListJob(), signaturetext, plainData ); - if ( allowAsync() ) { -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: allowAsync"; -#endif - QObject::connect( newM, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), - mSource->sourceObject(), SLOT(update(MessageViewer::Viewer::UpdateMode)) ); - if ( newM->start() ) { + PartMetaData messagePart; + messagePart.isSigned = true; + messagePart.technicalProblem = ( cryptProto == 0 ); + messagePart.isGoodSignature = false; + messagePart.isEncrypted = false; + messagePart.isDecryptable = false; + messagePart.keyTrust = Kpgp::KPGP_VALIDITY_UNKNOWN; + messagePart.status = i18n("Wrong Crypto Plug-In."); + messagePart.status_code = GPGME_SIG_STAT_NONE; + + GpgME::Key key; + + if ( doCheck && cryptProto ) { +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: doCheck and cryptProto"; +#endif + GpgME::VerificationResult result; + if ( data ) { // detached +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: is detached signature"; +#endif + const VerifyDetachedBodyPartMemento * m + = dynamic_cast( mNodeHelper->bodyPartMemento( &sign, "verifydetached" ) ); + if ( !m ) { +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: no memento available"; +#endif + Kleo::VerifyDetachedJob * job = cryptProto->verifyDetachedJob(); + if ( !job ) { + cryptPlugError = CANT_VERIFY_SIGNATURES; + // PENDING(marc) cryptProto = 0 here? + } else { + QByteArray plainData = cleartext; + VerifyDetachedBodyPartMemento * newM + = new VerifyDetachedBodyPartMemento( job, cryptProto->keyListJob(), signaturetext, plainData ); + if ( allowAsync() ) { +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: allowAsync"; +#endif + QObject::connect( newM, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), + mSource->sourceObject(), SLOT(update(MessageViewer::Viewer::UpdateMode)) ); + if ( newM->start() ) { +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: new memento started"; +#endif + messagePart.inProgress = true; + mHasPendingAsyncJobs = true; + } else { + m = newM; + } + } else { + newM->exec(); + m = newM; + } + mNodeHelper->setBodyPartMemento( &sign, "verifydetached", newM ); + } + } else if ( m->isRunning() ) { #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: new memento started"; + kDebug() << "tokoe: memento is running"; #endif - messagePart.inProgress = true; - mHasPendingAsyncJobs = true; - } else { - m = newM; + messagePart.inProgress = true; + mHasPendingAsyncJobs = true; + m = 0; } - } else { - newM->exec(); - m = newM; - } - mNodeHelper->setBodyPartMemento( &sign, "verifydetached", newM ); - } - } else if ( m->isRunning() ) { -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: memento is running"; -#endif - messagePart.inProgress = true; - mHasPendingAsyncJobs = true; - m = 0; - } - if ( m ) { -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: memento finished, assign result"; -#endif - result = m->verifyResult(); - messagePart.auditLogError = m->auditLogError(); - messagePart.auditLog = m->auditLogAsHtml(); - key = m->signingKey(); - } - } else { // opaque + if ( m ) { #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: is opaque signature"; + kDebug() << "tokoe: memento finished, assign result"; #endif - const VerifyOpaqueBodyPartMemento * m - = dynamic_cast( mNodeHelper->bodyPartMemento( &sign, "verifyopaque" ) ); - if ( !m ) { + result = m->verifyResult(); + messagePart.auditLogError = m->auditLogError(); + messagePart.auditLog = m->auditLogAsHtml(); + key = m->signingKey(); + } + } else { // opaque #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: no memento available"; + kDebug() << "tokoe: is opaque signature"; #endif - Kleo::VerifyOpaqueJob * job = cryptProto->verifyOpaqueJob(); - if ( !job ) { - cryptPlugError = CANT_VERIFY_SIGNATURES; - // PENDING(marc) cryptProto = 0 here? - } else { - VerifyOpaqueBodyPartMemento * newM - = new VerifyOpaqueBodyPartMemento( job, cryptProto->keyListJob(), signaturetext ); - if ( allowAsync() ) { + const VerifyOpaqueBodyPartMemento * m + = dynamic_cast( mNodeHelper->bodyPartMemento( &sign, "verifyopaque" ) ); + if ( !m ) { +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: no memento available"; +#endif + Kleo::VerifyOpaqueJob * job = cryptProto->verifyOpaqueJob(); + if ( !job ) { + cryptPlugError = CANT_VERIFY_SIGNATURES; + // PENDING(marc) cryptProto = 0 here? + } else { + VerifyOpaqueBodyPartMemento * newM + = new VerifyOpaqueBodyPartMemento( job, cryptProto->keyListJob(), signaturetext ); + if ( allowAsync() ) { +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: allowAsync"; +#endif + QObject::connect( newM, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), mSource->sourceObject(), + SLOT(update(MessageViewer::Viewer::UpdateMode)) ); + if ( newM->start() ) { +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: new memento started"; +#endif + messagePart.inProgress = true; + mHasPendingAsyncJobs = true; + } else { + m = newM; + } + } else { + newM->exec(); + m = newM; + } + mNodeHelper->setBodyPartMemento( &sign, "verifyopaque", newM ); + } + } else if ( m->isRunning() ) { #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: allowAsync"; + kDebug() << "tokoe: memento is running"; #endif - QObject::connect( newM, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), mSource->sourceObject(), - SLOT(update(MessageViewer::Viewer::UpdateMode)) ); - if ( newM->start() ) { + messagePart.inProgress = true; + mHasPendingAsyncJobs = true; + m = 0; + } + + if ( m ) { #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: new memento started"; + kDebug() << "tokoe: memento finished, assign result"; #endif - messagePart.inProgress = true; - mHasPendingAsyncJobs = true; - } else { - m = newM; + result = m->verifyResult(); + cleartext = m->plainText(); + messagePart.auditLogError = m->auditLogError(); + messagePart.auditLog = m->auditLogAsHtml(); + key = m->signingKey(); } - } else { - newM->exec(); - m = newM; - } - mNodeHelper->setBodyPartMemento( &sign, "verifyopaque", newM ); } - } else if ( m->isRunning() ) { -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: memento is running"; -#endif - messagePart.inProgress = true; - mHasPendingAsyncJobs = true; - m = 0; - } - - if ( m ) { + std::stringstream ss; + ss << result; #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: memento finished, assign result"; + kDebug() << ss.str().c_str(); #endif - result = m->verifyResult(); - cleartext = m->plainText(); - messagePart.auditLogError = m->auditLogError(); - messagePart.auditLog = m->auditLogAsHtml(); - key = m->signingKey(); - } + signatures = result.signatures(); } - std::stringstream ss; - ss << result; -#ifdef DEBUG_SIGNATURE - kDebug() << ss.str().c_str(); -#endif - signatures = result.signatures(); - } - else - messagePart.auditLogError = GpgME::Error( GPG_ERR_NOT_IMPLEMENTED ); + else + messagePart.auditLogError = GpgME::Error( GPG_ERR_NOT_IMPLEMENTED ); #ifdef DEBUG_SIGNATURE - if ( doCheck ) - kDebug() << "returned from CRYPTPLUG"; + if ( doCheck ) + kDebug() << "returned from CRYPTPLUG"; #endif - // ### only one signature supported - if ( !signatures.empty() ) { + // ### only one signature supported + if ( !signatures.empty() ) { #ifdef DEBUG_SIGNATURE - kDebug() << "\nFound signature"; + kDebug() << "\nFound signature"; #endif - GpgME::Signature signature = signatures.front(); + GpgME::Signature signature = signatures.front(); - messagePart.status_code = signatureToStatus( signature ); - messagePart.status = QString::fromLocal8Bit( signature.status().asString() ); - for ( uint i = 1; i < signatures.size(); ++i ) { - if ( signatureToStatus( signatures[i] ) != messagePart.status_code ) { - messagePart.status_code = GPGME_SIG_STAT_DIFF; - messagePart.status = i18n("Different results for signatures"); - } - } - if ( messagePart.status_code & GPGME_SIG_STAT_GOOD ) { - messagePart.isGoodSignature = true; - if ( !doCheck ) { - // We have a good signature but did not do a verify, - // this means the signature was already validated before by - // decryptverify for example. - Q_ASSERT( !key.keyID() ); // There should be no key set without doCheck - - // Search for the key by it's fingerprint so that we can check for - // trust etc. - Kleo::KeyListJob * job = cryptProto->keyListJob( false ); // local, no sigs - if ( !job ) { - kDebug() << "The Crypto backend does not support listing keys. "; - } else { - std::vector found_keys; - // As we are local it is ok to make this synchronous - GpgME::KeyListResult res = job->exec( QStringList( QLatin1String(signature.fingerprint()) ), false, found_keys ); - if ( res.error() ) { - kDebug() << "Error while searching key for Fingerprint: " << signature.fingerprint(); - } - if ( found_keys.size() > 1 ) { - // Should not Happen - kDebug() << "Oops: Found more then one Key for Fingerprint: " << signature.fingerprint(); - } - if ( found_keys.size() != 1 ) { - // Should not Happen at this point - kDebug() << "Oops: Found no Key for Fingerprint: " << signature.fingerprint(); - } else { - key = found_keys[0]; - } + messagePart.status_code = signatureToStatus( signature ); + messagePart.status = QString::fromLocal8Bit( signature.status().asString() ); + for ( uint i = 1; i < signatures.size(); ++i ) { + if ( signatureToStatus( signatures[i] ) != messagePart.status_code ) { + messagePart.status_code = GPGME_SIG_STAT_DIFF; + messagePart.status = i18n("Different results for signatures"); + } + } + if ( messagePart.status_code & GPGME_SIG_STAT_GOOD ) { + messagePart.isGoodSignature = true; + if ( !doCheck ) { + // We have a good signature but did not do a verify, + // this means the signature was already validated before by + // decryptverify for example. + Q_ASSERT( !key.keyID() ); // There should be no key set without doCheck + + // Search for the key by it's fingerprint so that we can check for + // trust etc. + Kleo::KeyListJob * job = cryptProto->keyListJob( false ); // local, no sigs + if ( !job ) { + kDebug() << "The Crypto backend does not support listing keys. "; + } else { + std::vector found_keys; + // As we are local it is ok to make this synchronous + GpgME::KeyListResult res = job->exec( QStringList( QLatin1String(signature.fingerprint()) ), false, found_keys ); + if ( res.error() ) { + kDebug() << "Error while searching key for Fingerprint: " << signature.fingerprint(); + } + if ( found_keys.size() > 1 ) { + // Should not Happen + kDebug() << "Oops: Found more then one Key for Fingerprint: " << signature.fingerprint(); + } + if ( found_keys.size() != 1 ) { + // Should not Happen at this point + kDebug() << "Oops: Found no Key for Fingerprint: " << signature.fingerprint(); + } else { + key = found_keys[0]; + } + } + } } - } - } - // save extended signature status flags - messagePart.sigSummary = signature.summary(); + // save extended signature status flags + messagePart.sigSummary = signature.summary(); - if ( key.keyID() ) - messagePart.keyId = key.keyID(); - if ( messagePart.keyId.isEmpty() ) - messagePart.keyId = signature.fingerprint(); - // ### Ugh. We depend on two enums being in sync: - messagePart.keyTrust = (Kpgp::Validity)signature.validity(); - if ( key.numUserIDs() > 0 && key.userID( 0 ).id() ) - messagePart.signer = Kleo::DN( key.userID( 0 ).id() ).prettyDN(); - for ( uint iMail = 0; iMail < key.numUserIDs(); ++iMail ) { - // The following if /should/ always result in TRUE but we - // won't trust implicitely the plugin that gave us these data. - if ( key.userID( iMail ).email() ) { - QString email = QString::fromUtf8( key.userID( iMail ).email() ); - // ### work around gpgme 0.3.x / cryptplug bug where the - // ### email addresses are specified as angle-addr, not addr-spec: - if ( email.startsWith( QLatin1Char('<') ) && email.endsWith( QLatin1Char('>') ) ) - email = email.mid( 1, email.length() - 2 ); - if ( !email.isEmpty() ) - messagePart.signerMailAddresses.append( email ); - } - } + if ( key.keyID() ) + messagePart.keyId = key.keyID(); + if ( messagePart.keyId.isEmpty() ) + messagePart.keyId = signature.fingerprint(); + // ### Ugh. We depend on two enums being in sync: + messagePart.keyTrust = (Kpgp::Validity)signature.validity(); + if ( key.numUserIDs() > 0 && key.userID( 0 ).id() ) + messagePart.signer = Kleo::DN( key.userID( 0 ).id() ).prettyDN(); + for ( uint iMail = 0; iMail < key.numUserIDs(); ++iMail ) { + // The following if /should/ always result in TRUE but we + // won't trust implicitely the plugin that gave us these data. + if ( key.userID( iMail ).email() ) { + QString email = QString::fromUtf8( key.userID( iMail ).email() ); + // ### work around gpgme 0.3.x / cryptplug bug where the + // ### email addresses are specified as angle-addr, not addr-spec: + if ( email.startsWith( QLatin1Char('<') ) && email.endsWith( QLatin1Char('>') ) ) + email = email.mid( 1, email.length() - 2 ); + if ( !email.isEmpty() ) + messagePart.signerMailAddresses.append( email ); + } + } - if ( signature.creationTime() ) - messagePart.creationTime.setTime_t( signature.creationTime() ); - else - messagePart.creationTime = QDateTime(); - if ( messagePart.signer.isEmpty() ) { - if ( key.numUserIDs() > 0 && key.userID( 0 ).name() ) - messagePart.signer = Kleo::DN( key.userID( 0 ).name() ).prettyDN(); - if ( !messagePart.signerMailAddresses.empty() ) { - if ( messagePart.signer.isEmpty() ) - messagePart.signer = messagePart.signerMailAddresses.front(); + if ( signature.creationTime() ) + messagePart.creationTime.setTime_t( signature.creationTime() ); else - messagePart.signer += QLatin1String(" <") + messagePart.signerMailAddresses.front() + QLatin1Char('>'); - } - } + messagePart.creationTime = QDateTime(); + if ( messagePart.signer.isEmpty() ) { + if ( key.numUserIDs() > 0 && key.userID( 0 ).name() ) + messagePart.signer = Kleo::DN( key.userID( 0 ).name() ).prettyDN(); + if ( !messagePart.signerMailAddresses.empty() ) { + if ( messagePart.signer.isEmpty() ) + messagePart.signer = messagePart.signerMailAddresses.front(); + else + messagePart.signer += QLatin1String(" <") + messagePart.signerMailAddresses.front() + QLatin1Char('>'); + } + } #ifdef DEBUG_SIGNATURE - kDebug() << "\n key id:" << messagePart.keyId - << "\n key trust:" << messagePart.keyTrust - << "\n signer:" << messagePart.signer; + kDebug() << "\n key id:" << messagePart.keyId + << "\n key trust:" << messagePart.keyTrust + << "\n signer:" << messagePart.signer; #endif - } else { - messagePart.creationTime = QDateTime(); - } + } else { + messagePart.creationTime = QDateTime(); + } - if ( !doCheck || !data ){ - if ( cleartextData || !cleartext.isEmpty() ) { - if ( htmlWriter() ) - htmlWriter()->queue( writeSigstatHeader( messagePart, - cryptProto, - fromAddress ) ); - bIsOpaqueSigned = true; - - CryptoProtocolSaver cpws( this, cryptProto ); - createAndParseTempNode( &sign, doCheck ? cleartext.data() : cleartextData->data(), - "opaque signed data" ); + if ( !doCheck || !data ){ + if ( cleartextData || !cleartext.isEmpty() ) { + if ( htmlWriter() ) + htmlWriter()->queue( writeSigstatHeader( messagePart, + cryptProto, + fromAddress ) ); + bIsOpaqueSigned = true; + + CryptoProtocolSaver cpws( this, cryptProto ); + createAndParseTempNode( &sign, doCheck ? cleartext.data() : cleartextData->data(), + "opaque signed data" ); - if ( htmlWriter() ) - htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + if ( htmlWriter() ) + htmlWriter()->queue( writeSigstatFooter( messagePart ) ); - } - else if ( !hideErrors ) { - QString txt; - txt = QLatin1String("

"); - txt.append( i18n( "The crypto engine returned no cleartext data." ) ); - txt.append( QLatin1String("

" )); - txt.append( QLatin1String("
 
") ); - txt.append( i18n( "Status: " ) ); - if ( !messagePart.status.isEmpty() ) { - txt.append( QLatin1String("") ); - txt.append( messagePart.status ); - txt.append( QLatin1String("") ); - } - else - txt.append( i18nc("Status of message unknown.","(unknown)") ); - if ( htmlWriter() ) - htmlWriter()->queue(txt); - } - } - else { - if ( htmlWriter() ) { - if ( !cryptProto ) { - QString errorMsg; - switch ( cryptPlugError ) { - case NOT_INITIALIZED: - errorMsg = i18n( "Crypto plug-in \"%1\" is not initialized.", - cryptPlugLibName ); - break; - case CANT_VERIFY_SIGNATURES: - errorMsg = i18n( "Crypto plug-in \"%1\" cannot verify signatures.", - cryptPlugLibName ); - break; - case NO_PLUGIN: - if ( cryptPlugDisplayName.isEmpty() ) - errorMsg = i18n( "No appropriate crypto plug-in was found." ); - else - errorMsg = i18nc( "%1 is either 'OpenPGP' or 'S/MIME'", - "No %1 plug-in was found.", - cryptPlugDisplayName ); - break; } - messagePart.errorText = i18n( "The message is signed, but the " - "validity of the signature cannot be " - "verified.
" - "Reason: %1", - errorMsg ); - } - - htmlWriter()->queue( writeSigstatHeader( messagePart, - cryptProto, - fromAddress ) ); + else if ( !hideErrors ) { + QString txt; + txt = QLatin1String("

"); + txt.append( i18n( "The crypto engine returned no cleartext data." ) ); + txt.append( QLatin1String("

" )); + txt.append( QLatin1String("
 
") ); + txt.append( i18n( "Status: " ) ); + if ( !messagePart.status.isEmpty() ) { + txt.append( QLatin1String("") ); + txt.append( messagePart.status ); + txt.append( QLatin1String("") ); + } + else + txt.append( i18nc("Status of message unknown.","(unknown)") ); + if ( htmlWriter() ) + htmlWriter()->queue(txt); + } } + else { + if ( htmlWriter() ) { + if ( !cryptProto ) { + QString errorMsg; + switch ( cryptPlugError ) { + case NOT_INITIALIZED: + errorMsg = i18n( "Crypto plug-in \"%1\" is not initialized.", + cryptPlugLibName ); + break; + case CANT_VERIFY_SIGNATURES: + errorMsg = i18n( "Crypto plug-in \"%1\" cannot verify signatures.", + cryptPlugLibName ); + break; + case NO_PLUGIN: + if ( cryptPlugDisplayName.isEmpty() ) + errorMsg = i18n( "No appropriate crypto plug-in was found." ); + else + errorMsg = i18nc( "%1 is either 'OpenPGP' or 'S/MIME'", + "No %1 plug-in was found.", + cryptPlugDisplayName ); + break; + } + messagePart.errorText = i18n( "The message is signed, but the " + "validity of the signature cannot be " + "verified.
" + "Reason: %1", + errorMsg ); + } - ObjectTreeParser otp( this, true ); - otp.setAllowAsync( allowAsync() ); - otp.parseObjectTreeInternal( data ); - copyContentFrom( &otp ); + htmlWriter()->queue( writeSigstatHeader( messagePart, + cryptProto, + fromAddress ) ); + } - if ( htmlWriter() ) - htmlWriter()->queue( writeSigstatFooter( messagePart ) ); - } + ObjectTreeParser otp( this, true ); + otp.setAllowAsync( allowAsync() ); + otp.parseObjectTreeInternal( data ); + copyContentFrom( &otp ); + + if ( htmlWriter() ) + htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + } #ifdef DEBUG_SIGNATURE - kDebug() << "done, returning" << ( bIsOpaqueSigned ? "TRUE" : "FALSE" ); + kDebug() << "done, returning" << ( bIsOpaqueSigned ? "TRUE" : "FALSE" ); #endif - //kDebug() << "DECRYPTED" << data; - return bIsOpaqueSigned; + //kDebug() << "DECRYPTED" << data; + return bIsOpaqueSigned; } void ObjectTreeParser::writeDeferredDecryptionBlock() { - const QString iconName = QLatin1String("file:///") + KIconLoader::global()->iconPath( QLatin1String("document-decrypt"), - KIconLoader::Small ); - const QString decryptedData = QLatin1String("
") - + i18n("This message is encrypted.") - + QLatin1String("
" - ""); - PartMetaData messagePart; - messagePart.isDecryptable = true; - messagePart.isEncrypted = true; - messagePart.isSigned = false; - mRawDecryptedBody += decryptedData.toUtf8(); + const QString iconName = QLatin1String("file:///") + KIconLoader::global()->iconPath( QLatin1String("document-decrypt"), + KIconLoader::Small ); + const QString decryptedData = QLatin1String("
") + + i18n("This message is encrypted.") + + QLatin1String("
" + ""); + PartMetaData messagePart; + messagePart.isDecryptable = true; + messagePart.isEncrypted = true; + messagePart.isSigned = false; + mRawDecryptedBody += decryptedData.toUtf8(); - if ( htmlWriter() ) { //TODO: check if this check should be here or at the beginning of the method - htmlWriter()->queue( writeSigstatHeader( messagePart, - cryptoProtocol(), - QString() ) ); - htmlWriter()->queue( decryptedData ); - htmlWriter()->queue( writeSigstatFooter( messagePart ) ); - } + if ( htmlWriter() ) { //TODO: check if this check should be here or at the beginning of the method + htmlWriter()->queue( writeSigstatHeader( messagePart, + cryptoProtocol(), + QString() ) ); + htmlWriter()->queue( decryptedData ); + htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + } } void ObjectTreeParser::writeDecryptionInProgressBlock() { - if ( !htmlWriter() ) - return; - // PENDING(marc) find an animated icon here: - //const QString iconName = KGlobal::instance()->iconLoader()->iconPath( "decrypted", KIcon::Small ); - const QString decryptedData = i18n("Encrypted data not shown"); - PartMetaData messagePart; - messagePart.isDecryptable = true; - messagePart.isEncrypted = true; - messagePart.isSigned = false; - messagePart.inProgress = true; - htmlWriter()->queue( writeSigstatHeader( messagePart, - cryptoProtocol(), - QString() ) ); - //htmlWriter()->queue( decryptedData ); - htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + if ( !htmlWriter() ) + return; + // PENDING(marc) find an animated icon here: + //const QString iconName = KGlobal::instance()->iconLoader()->iconPath( "decrypted", KIcon::Small ); + const QString decryptedData = i18n("Encrypted data not shown"); + PartMetaData messagePart; + messagePart.isDecryptable = true; + messagePart.isEncrypted = true; + messagePart.isSigned = false; + messagePart.inProgress = true; + htmlWriter()->queue( writeSigstatHeader( messagePart, + cryptoProtocol(), + QString() ) ); + //htmlWriter()->queue( decryptedData ); + htmlWriter()->queue( writeSigstatFooter( messagePart ) ); } void ObjectTreeParser::writeCertificateImportResult( const GpgME::ImportResult & res ) { if ( res.error() ) { - htmlWriter()->queue( i18n( "Sorry, certificate could not be imported.
" - "Reason: %1", QString::fromLocal8Bit( res.error().asString() ) ) ); - return; + htmlWriter()->queue( i18n( "Sorry, certificate could not be imported.
" + "Reason: %1", QString::fromLocal8Bit( res.error().asString() ) ) ); + return; } const int nImp = res.numImported(); @@ -938,47 +938,47 @@ const int nSKImp = res.numSecretKeysImported(); const int nSKUnc = res.numSecretKeysUnchanged(); if ( !nImp && !nSKImp && !nUnc && !nSKUnc ) { - htmlWriter()->queue( i18n( "Sorry, no certificates were found in this message." ) ); - return; + htmlWriter()->queue( i18n( "Sorry, no certificates were found in this message." ) ); + return; } QString comment = QLatin1String("") + i18n( "Certificate import status:" ) + QLatin1String("
 
"); if ( nImp ) - comment += i18np( "1 new certificate was imported.", - "%1 new certificates were imported.", nImp ) + QLatin1String("
"); + comment += i18np( "1 new certificate was imported.", + "%1 new certificates were imported.", nImp ) + QLatin1String("
"); if ( nUnc ) - comment += i18np( "1 certificate was unchanged.", - "%1 certificates were unchanged.", nUnc ) + QLatin1String("
"); + comment += i18np( "1 certificate was unchanged.", + "%1 certificates were unchanged.", nUnc ) + QLatin1String("
"); if ( nSKImp ) - comment += i18np( "1 new secret key was imported.", - "%1 new secret keys were imported.", nSKImp ) + QLatin1String("
"); + comment += i18np( "1 new secret key was imported.", + "%1 new secret keys were imported.", nSKImp ) + QLatin1String("
"); if ( nSKUnc ) - comment += i18np( "1 secret key was unchanged.", - "%1 secret keys were unchanged.", nSKUnc ) + QLatin1String("
"); + comment += i18np( "1 secret key was unchanged.", + "%1 secret keys were unchanged.", nSKUnc ) + QLatin1String("
"); comment += QLatin1String(" 
"); htmlWriter()->queue( comment ); if ( !nImp && !nSKImp ) { - htmlWriter()->queue( QLatin1String("
") ); - return; + htmlWriter()->queue( QLatin1String("
") ); + return; } const std::vector imports = res.imports(); if ( imports.empty() ) { - htmlWriter()->queue( i18n( "Sorry, no details on certificate import available." ) + QLatin1String("
") ); - return; + htmlWriter()->queue( i18n( "Sorry, no details on certificate import available." ) + QLatin1String("
") ); + return; } htmlWriter()->queue( QLatin1String("") + i18n( "Certificate import details:" ) + QLatin1String("
") ); std::vector::const_iterator end( imports.end() ); for ( std::vector::const_iterator it = imports.begin() ; it != end ; ++it ) { - if ( (*it).error() ) { - htmlWriter()->queue( i18nc( "Certificate import failed.", "Failed: %1 (%2)", QLatin1String((*it).fingerprint()), - QString::fromLocal8Bit( (*it).error().asString() ) ) ); - } else if ( (*it).status() & ~GpgME::Import::ContainedSecretKey ) { - if ( (*it).status() & GpgME::Import::ContainedSecretKey ) { - htmlWriter()->queue( i18n( "New or changed: %1 (secret key available)", QLatin1String((*it).fingerprint() )) ); - } else { - htmlWriter()->queue( i18n( "New or changed: %1", QLatin1String((*it).fingerprint() )) ); + if ( (*it).error() ) { + htmlWriter()->queue( i18nc( "Certificate import failed.", "Failed: %1 (%2)", QLatin1String((*it).fingerprint()), + QString::fromLocal8Bit( (*it).error().asString() ) ) ); + } else if ( (*it).status() & ~GpgME::Import::ContainedSecretKey ) { + if ( (*it).status() & GpgME::Import::ContainedSecretKey ) { + htmlWriter()->queue( i18n( "New or changed: %1 (secret key available)", QLatin1String((*it).fingerprint() )) ); + } else { + htmlWriter()->queue( i18n( "New or changed: %1", QLatin1String((*it).fingerprint() )) ); + } } - } - htmlWriter()->queue( QLatin1String("
") ); + htmlWriter()->queue( QLatin1String("
") ); } htmlWriter()->queue( QLatin1String("
") ); @@ -986,1188 +986,1188 @@ bool ObjectTreeParser::okDecryptMIME( KMime::Content& data, - QByteArray& decryptedData, - bool& signatureFound, - std::vector &signatures, - bool showWarning, - bool& passphraseError, - bool& actuallyEncrypted, - bool& decryptionStarted, - PartMetaData &partMetaData ) -{ - passphraseError = false; - decryptionStarted = false; - partMetaData.errorText.clear(); - partMetaData.auditLogError = GpgME::Error(); - partMetaData.auditLog.clear(); - bool bDecryptionOk = false; - enum { NO_PLUGIN, NOT_INITIALIZED, CANT_DECRYPT } - cryptPlugError = NO_PLUGIN; - - const Kleo::CryptoBackend::Protocol* cryptProto = cryptoProtocol(); - - QString cryptPlugLibName; - if ( cryptProto ) - cryptPlugLibName = cryptProto->name(); - - assert( mSource->decryptMessage() ); - - const QString errorMsg = i18n( "Could not decrypt the data." ); - if ( cryptProto /*FIXME(Andras) port to akonadi - && !kmkernel->contextMenuShown()*/ ) { - QByteArray ciphertext = data.decodedContent(); - #ifdef MARCS_DEBUG - QString cipherStr = QString::fromLatin1( ciphertext ); - bool cipherIsBinary = ( !cipherStr.contains("BEGIN ENCRYPTED MESSAGE", Qt::CaseInsensitive ) ) && - ( !cipherStr.contains("BEGIN PGP ENCRYPTED MESSAGE", Qt::CaseInsensitive ) ) && - ( !cipherStr.contains("BEGIN PGP MESSAGE", Qt::CaseInsensitive ) ); - - dumpToFile( "dat_04_reader.encrypted", ciphertext.data(), ciphertext.size() ); - - QString deb; - deb = "\n\nE N C R Y P T E D D A T A = "; - if ( cipherIsBinary ) - deb += "[binary data]"; - else { - deb += "\""; - deb += cipherStr; - deb += "\""; - } - deb += "\n\n"; - kDebug() << deb; - #endif - - - //kDebug() << "going to call CRYPTPLUG" << cryptPlugLibName; - - // Check whether the memento contains a result from last time: - const DecryptVerifyBodyPartMemento * m - = dynamic_cast( mNodeHelper->bodyPartMemento( &data, "decryptverify" ) ); - if ( !m ) { - Kleo::DecryptVerifyJob * job = cryptProto->decryptVerifyJob(); - if ( !job ) { - cryptPlugError = CANT_DECRYPT; - cryptProto = 0; - } else { - DecryptVerifyBodyPartMemento * newM - = new DecryptVerifyBodyPartMemento( job, ciphertext ); - if ( allowAsync() ) { - QObject::connect( newM, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), mSource->sourceObject(), - SLOT(update(MessageViewer::Viewer::UpdateMode)) ); - if ( newM->start() ) { + QByteArray& decryptedData, + bool& signatureFound, + std::vector &signatures, + bool showWarning, + bool& passphraseError, + bool& actuallyEncrypted, + bool& decryptionStarted, + PartMetaData &partMetaData ) +{ + passphraseError = false; + decryptionStarted = false; + partMetaData.errorText.clear(); + partMetaData.auditLogError = GpgME::Error(); + partMetaData.auditLog.clear(); + bool bDecryptionOk = false; + enum { NO_PLUGIN, NOT_INITIALIZED, CANT_DECRYPT } + cryptPlugError = NO_PLUGIN; + + const Kleo::CryptoBackend::Protocol* cryptProto = cryptoProtocol(); + + QString cryptPlugLibName; + if ( cryptProto ) + cryptPlugLibName = cryptProto->name(); + + assert( mSource->decryptMessage() ); + + const QString errorMsg = i18n( "Could not decrypt the data." ); + if ( cryptProto /*FIXME(Andras) port to akonadi + && !kmkernel->contextMenuShown()*/ ) { + QByteArray ciphertext = data.decodedContent(); +#ifdef MARCS_DEBUG + QString cipherStr = QString::fromLatin1( ciphertext ); + bool cipherIsBinary = ( !cipherStr.contains("BEGIN ENCRYPTED MESSAGE", Qt::CaseInsensitive ) ) && + ( !cipherStr.contains("BEGIN PGP ENCRYPTED MESSAGE", Qt::CaseInsensitive ) ) && + ( !cipherStr.contains("BEGIN PGP MESSAGE", Qt::CaseInsensitive ) ); + + dumpToFile( "dat_04_reader.encrypted", ciphertext.data(), ciphertext.size() ); + + QString deb; + deb = "\n\nE N C R Y P T E D D A T A = "; + if ( cipherIsBinary ) + deb += "[binary data]"; + else { + deb += "\""; + deb += cipherStr; + deb += "\""; + } + deb += "\n\n"; + kDebug() << deb; +#endif + + + //kDebug() << "going to call CRYPTPLUG" << cryptPlugLibName; + + // Check whether the memento contains a result from last time: + const DecryptVerifyBodyPartMemento * m + = dynamic_cast( mNodeHelper->bodyPartMemento( &data, "decryptverify" ) ); + if ( !m ) { + Kleo::DecryptVerifyJob * job = cryptProto->decryptVerifyJob(); + if ( !job ) { + cryptPlugError = CANT_DECRYPT; + cryptProto = 0; + } else { + DecryptVerifyBodyPartMemento * newM + = new DecryptVerifyBodyPartMemento( job, ciphertext ); + if ( allowAsync() ) { + QObject::connect( newM, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), mSource->sourceObject(), + SLOT(update(MessageViewer::Viewer::UpdateMode)) ); + if ( newM->start() ) { + decryptionStarted = true; + mHasPendingAsyncJobs = true; + } else { + m = newM; + } + } else { + newM->exec(); + m = newM; + } + mNodeHelper->setBodyPartMemento( &data, "decryptverify", newM ); + } + } else if ( m->isRunning() ) { decryptionStarted = true; mHasPendingAsyncJobs = true; - } else { - m = newM; - } - } else { - newM->exec(); - m = newM; + m = 0; } - mNodeHelper->setBodyPartMemento( &data, "decryptverify", newM ); - } - } else if ( m->isRunning() ) { - decryptionStarted = true; - mHasPendingAsyncJobs = true; - m = 0; - } - - if ( m ) { - const QByteArray & plainText = m->plainText(); - const GpgME::DecryptionResult & decryptResult = m->decryptResult(); - const GpgME::VerificationResult & verifyResult = m->verifyResult(); - std::stringstream ss; - ss << decryptResult << '\n' << verifyResult; - //kDebug() << ss.str().c_str(); - signatureFound = verifyResult.signatures().size() > 0; - signatures = verifyResult.signatures(); - bDecryptionOk = !decryptResult.error(); - passphraseError = decryptResult.error().isCanceled() - || decryptResult.error().code() == GPG_ERR_NO_SECKEY; - actuallyEncrypted = decryptResult.error().code() != GPG_ERR_NO_DATA; - partMetaData.errorText = QString::fromLocal8Bit( decryptResult.error().asString() ); - partMetaData.auditLogError = m->auditLogError(); - partMetaData.auditLog = m->auditLogAsHtml(); - partMetaData.isEncrypted = actuallyEncrypted; - if ( actuallyEncrypted && decryptResult.numRecipients() > 0 ) - partMetaData.keyId = decryptResult.recipient( 0 ).keyID(); - - //kDebug() << "ObjectTreeParser::decryptMIME: returned from CRYPTPLUG"; - if ( bDecryptionOk ) - decryptedData = plainText; - else if ( htmlWriter() && showWarning ) { - decryptedData = "
plainText(); + const GpgME::DecryptionResult & decryptResult = m->decryptResult(); + const GpgME::VerificationResult & verifyResult = m->verifyResult(); + std::stringstream ss; + ss << decryptResult << '\n' << verifyResult; + //kDebug() << ss.str().c_str(); + signatureFound = verifyResult.signatures().size() > 0; + signatures = verifyResult.signatures(); + bDecryptionOk = !decryptResult.error(); + passphraseError = decryptResult.error().isCanceled() + || decryptResult.error().code() == GPG_ERR_NO_SECKEY; + actuallyEncrypted = decryptResult.error().code() != GPG_ERR_NO_DATA; + partMetaData.errorText = QString::fromLocal8Bit( decryptResult.error().asString() ); + partMetaData.auditLogError = m->auditLogError(); + partMetaData.auditLog = m->auditLogAsHtml(); + partMetaData.isEncrypted = actuallyEncrypted; + if ( actuallyEncrypted && decryptResult.numRecipients() > 0 ) + partMetaData.keyId = decryptResult.recipient( 0 ).keyID(); + + //kDebug() << "ObjectTreeParser::decryptMIME: returned from CRYPTPLUG"; + if ( bDecryptionOk ) + decryptedData = plainText; + else if ( htmlWriter() && showWarning ) { + decryptedData = "
" - + errorMsg.toUtf8() - + "
"; - if ( !passphraseError ) - partMetaData.errorText = i18n("Crypto plug-in \"%1\" could not decrypt the data.", cryptPlugLibName ) - + QLatin1String("
") - + i18n("Error: %1", partMetaData.errorText ); - } + + errorMsg.toUtf8() + + "
"; + if ( !passphraseError ) + partMetaData.errorText = i18n("Crypto plug-in \"%1\" could not decrypt the data.", cryptPlugLibName ) + + QLatin1String("
") + + i18n("Error: %1", partMetaData.errorText ); + } + } } -} -if ( !cryptProto ) { - decryptedData = "
" + if ( !cryptProto ) { + decryptedData = "
" + errorMsg.toUtf8() + "
"; - switch ( cryptPlugError ) { - case NOT_INITIALIZED: - partMetaData.errorText = i18n( "Crypto plug-in \"%1\" is not initialized.", - cryptPlugLibName ); - break; - case CANT_DECRYPT: - partMetaData.errorText = i18n( "Crypto plug-in \"%1\" cannot decrypt messages.", - cryptPlugLibName ); - break; - case NO_PLUGIN: - partMetaData.errorText = i18n( "No appropriate crypto plug-in was found." ); - break; - } -} else if (/*FIXME(Andras) port to akonadi - kmkernel->contextMenuShown()*/ false ) { - // ### Workaround for bug 56693 (kmail freeze with the complete desktop - // ### while pinentry-qt appears) - QByteArray ciphertext( data.decodedContent() ); - QString cipherStr = QString::fromLatin1( ciphertext ); - bool cipherIsBinary = ( !cipherStr.contains(QLatin1String("BEGIN ENCRYPTED MESSAGE"), Qt::CaseInsensitive ) ) && - ( !cipherStr.contains(QLatin1String("BEGIN PGP ENCRYPTED MESSAGE"), Qt::CaseInsensitive ) ) && - ( !cipherStr.contains(QLatin1String("BEGIN PGP MESSAGE"), Qt::CaseInsensitive ) ); - if ( !cipherIsBinary ) { - decryptedData = ciphertext; - } - else { - decryptedData = "
contextMenuShown()*/ false ) { + // ### Workaround for bug 56693 (kmail freeze with the complete desktop + // ### while pinentry-qt appears) + QByteArray ciphertext( data.decodedContent() ); + QString cipherStr = QString::fromLatin1( ciphertext ); + bool cipherIsBinary = ( !cipherStr.contains(QLatin1String("BEGIN ENCRYPTED MESSAGE"), Qt::CaseInsensitive ) ) && + ( !cipherStr.contains(QLatin1String("BEGIN PGP ENCRYPTED MESSAGE"), Qt::CaseInsensitive ) ) && + ( !cipherStr.contains(QLatin1String("BEGIN PGP MESSAGE"), Qt::CaseInsensitive ) ); + if ( !cipherIsBinary ) { + decryptedData = ciphertext; + } + else { + decryptedData = "
" - + errorMsg.toUtf8() - + "
"; - } -} + + errorMsg.toUtf8() + + "
"; + } + } -dumpToFile( "dat_05_reader.decrypted", decryptedData.data(), decryptedData.size() ); + dumpToFile( "dat_05_reader.decrypted", decryptedData.data(), decryptedData.size() ); -return bDecryptionOk; + return bDecryptionOk; } //static bool ObjectTreeParser::containsExternalReferences( const QString & str, const QString&extraHead ) { - const bool hasBaseInHeader = extraHead.contains(QLatin1String("= 0 || httpsPos >= 0 ) { - // pos = index of next occurrence of "http: or "https: whichever comes first - int pos = ( httpPos < httpsPos ) - ? ( ( httpPos >= 0 ) ? httpPos : httpsPos ) - : ( ( httpsPos >= 0 ) ? httpsPos : httpPos ); - // look backwards for "href" - if ( pos > 5 ) { - int hrefPos = str.lastIndexOf( QLatin1String("href"), pos - 5, Qt::CaseInsensitive ); - // if no 'href' is found or the distance between 'href' and '"http[s]:' - // is larger than 7 (7 is the distance in 'href = "http[s]:') then - // we assume that we have found an external reference - if ( ( hrefPos == -1 ) || ( pos - hrefPos > 7 ) ) { - - // HTML messages created by KMail itself for now contain the following: - // - // Make sure not to show an external references warning for this string - int dtdPos = str.indexOf( QLatin1String("http://www.w3.org/TR/html4/loose.dtd"), pos + 1 ); - if ( dtdPos != ( pos + 1 ) ) - return true; - } - } - // find next occurrence of "http: or "https: - if ( pos == httpPos ) { - httpPos = str.indexOf( QLatin1String("\"http:"), httpPos + 6, Qt::CaseInsensitive ); - } - else { - httpsPos = str.indexOf( QLatin1String("\"https:"), httpsPos + 7, Qt::CaseInsensitive ); + while ( httpPos >= 0 || httpsPos >= 0 ) { + // pos = index of next occurrence of "http: or "https: whichever comes first + int pos = ( httpPos < httpsPos ) + ? ( ( httpPos >= 0 ) ? httpPos : httpsPos ) + : ( ( httpsPos >= 0 ) ? httpsPos : httpPos ); + // look backwards for "href" + if ( pos > 5 ) { + int hrefPos = str.lastIndexOf( QLatin1String("href"), pos - 5, Qt::CaseInsensitive ); + // if no 'href' is found or the distance between 'href' and '"http[s]:' + // is larger than 7 (7 is the distance in 'href = "http[s]:') then + // we assume that we have found an external reference + if ( ( hrefPos == -1 ) || ( pos - hrefPos > 7 ) ) { + + // HTML messages created by KMail itself for now contain the following: + // + // Make sure not to show an external references warning for this string + int dtdPos = str.indexOf( QLatin1String("http://www.w3.org/TR/html4/loose.dtd"), pos + 1 ); + if ( dtdPos != ( pos + 1 ) ) + return true; + } + } + // find next occurrence of "http: or "https: + if ( pos == httpPos ) { + httpPos = str.indexOf( QLatin1String("\"http:"), httpPos + 6, Qt::CaseInsensitive ); + } + else { + httpsPos = str.indexOf( QLatin1String("\"https:"), httpsPos + 7, Qt::CaseInsensitive ); + } } - } - return false; + return false; } bool ObjectTreeParser::processTextHtmlSubtype( KMime::Content * curNode, ProcessResult & ) { - const QByteArray partBody( curNode->decodedContent() ); - - const QString bodyHTML = codecFor( curNode )->toUnicode( partBody ); - mHtmlContent += bodyHTML; - mHtmlContentCharset = NodeHelper::charset( curNode ); - mRawDecryptedBody = partBody; + const QByteArray partBody( curNode->decodedContent() ); - if ( !htmlWriter() ) - return true; + const QString bodyHTML = codecFor( curNode )->toUnicode( partBody ); + mHtmlContent += bodyHTML; + mHtmlContentCharset = NodeHelper::charset( curNode ); + mRawDecryptedBody = partBody; - QString bodyText; - if ( mSource->htmlMail() ) { - bodyText = bodyHTML; - } else { - bodyText = QLatin1String(StringUtil::convertAngleBracketsToHtml( partBody )); - } + if ( !htmlWriter() ) + return true; - if ( curNode->topLevel()->textContent() == curNode || attachmentStrategy()->defaultDisplay( curNode ) == AttachmentStrategy::Inline || - showOnlyOneMimePart() ) - { + QString bodyText; if ( mSource->htmlMail() ) { - - HTMLQuoteColorer colorer; - QString extraHead; - for ( int i = 0; i < 3; ++i ) - colorer.setQuoteColor( i, cssHelper()->quoteColor( i ) ); - bodyText = colorer.process( bodyText, extraHead ); - mNodeHelper->setNodeDisplayedEmbedded( curNode, true ); - htmlWriter()->extraHead(extraHead); - - // Show the "external references" warning (with possibility to load - // external references only if loading external references is disabled - // and the HTML code contains obvious external references). For - // messages where the external references are obfuscated the user won't - // have an easy way to load them but that shouldn't be a problem - // because only spam contains obfuscated external references. - if ( !mSource->htmlLoadExternal() && - containsExternalReferences( bodyText,extraHead ) ) { - htmlWriter()->queue( QLatin1String("
\n") ); - htmlWriter()->queue( i18n("Note: This HTML message may contain external " - "references to images etc. For security/privacy reasons " - "external references are not loaded. If you trust the " - "sender of this message then you can load the external " - "references for this message " - "by clicking here.") ); - htmlWriter()->queue( QLatin1String("


") ); - } + bodyText = bodyHTML; } else { - htmlWriter()->queue( QLatin1String("
\n") ); - htmlWriter()->queue( i18n("Note: This is an HTML message. For " - "security reasons, only the raw HTML code " - "is shown. If you trust the sender of this " - "message then you can activate formatted " - "HTML display for this message " - "by clicking here.") ); - htmlWriter()->queue( QLatin1String("


") ); - } - // Make sure the body is relative, so that nothing is painted over above "Note: ..." - // if a malicious message uses absolute positioning. #137643 - htmlWriter()->queue( QLatin1String("
\n") ); - htmlWriter()->queue( bodyText ); - htmlWriter()->queue( QLatin1String("
\n" )); - mSource->setHtmlMode( Util::Html ); - return true; - } - return false; + bodyText = QLatin1String(StringUtil::convertAngleBracketsToHtml( partBody )); + } + + if ( curNode->topLevel()->textContent() == curNode || attachmentStrategy()->defaultDisplay( curNode ) == AttachmentStrategy::Inline || + showOnlyOneMimePart() ) + { + if ( mSource->htmlMail() ) { + + HTMLQuoteColorer colorer; + QString extraHead; + for ( int i = 0; i < 3; ++i ) + colorer.setQuoteColor( i, cssHelper()->quoteColor( i ) ); + bodyText = colorer.process( bodyText, extraHead ); + mNodeHelper->setNodeDisplayedEmbedded( curNode, true ); + htmlWriter()->extraHead(extraHead); + + // Show the "external references" warning (with possibility to load + // external references only if loading external references is disabled + // and the HTML code contains obvious external references). For + // messages where the external references are obfuscated the user won't + // have an easy way to load them but that shouldn't be a problem + // because only spam contains obfuscated external references. + if ( !mSource->htmlLoadExternal() && + containsExternalReferences( bodyText,extraHead ) ) { + htmlWriter()->queue( QLatin1String("
\n") ); + htmlWriter()->queue( i18n("Note: This HTML message may contain external " + "references to images etc. For security/privacy reasons " + "external references are not loaded. If you trust the " + "sender of this message then you can load the external " + "references for this message " + "by clicking here.") ); + htmlWriter()->queue( QLatin1String("


") ); + } + } else { + htmlWriter()->queue( QLatin1String("
\n") ); + htmlWriter()->queue( i18n("Note: This is an HTML message. For " + "security reasons, only the raw HTML code " + "is shown. If you trust the sender of this " + "message then you can activate formatted " + "HTML display for this message " + "by clicking here.") ); + htmlWriter()->queue( QLatin1String("


") ); + } + // Make sure the body is relative, so that nothing is painted over above "Note: ..." + // if a malicious message uses absolute positioning. #137643 + htmlWriter()->queue( QLatin1String("
\n") ); + htmlWriter()->queue( bodyText ); + htmlWriter()->queue( QLatin1String("
\n" )); + mSource->setHtmlMode( Util::Html ); + return true; + } + return false; } bool ObjectTreeParser::isMailmanMessage( KMime::Content * curNode ) { - if ( !curNode || curNode->head().isEmpty() ) - return false; - if ( curNode->hasHeader("X-Mailman-Version") ) - return true; - if ( curNode->hasHeader("X-Mailer") ) { - KMime::Headers::Base *header = curNode->headerByType("X-Mailer"); - if ( header->asUnicodeString().contains(QLatin1String("MAILMAN"), Qt::CaseInsensitive ) ) + if ( !curNode || curNode->head().isEmpty() ) + return false; + if ( curNode->hasHeader("X-Mailman-Version") ) return true; - } - return false; + if ( curNode->hasHeader("X-Mailer") ) { + KMime::Headers::Base *header = curNode->headerByType("X-Mailer"); + if ( header->asUnicodeString().contains(QLatin1String("MAILMAN"), Qt::CaseInsensitive ) ) + return true; + } + return false; } bool ObjectTreeParser::processMailmanMessage( KMime::Content* curNode ) { - const QString str = QString::fromLatin1( curNode->decodedContent() ); + const QString str = QString::fromLatin1( curNode->decodedContent() ); - //### - const QLatin1String delim1( "--__--__--\n\nMessage:" ); - const QLatin1String delim2( "--__--__--\r\n\r\nMessage:" ); - const QLatin1String delimZ2( "--__--__--\n\n_____________" ); - const QLatin1String delimZ1( "--__--__--\r\n\r\n_____________" ); - QString partStr, digestHeaderStr; - int thisDelim = str.indexOf( delim1, Qt::CaseInsensitive ); - if ( thisDelim == -1 ) { - thisDelim = str.indexOf( delim2, Qt::CaseInsensitive ); - } - if ( thisDelim == -1 ) { - return false; - } + //### + const QLatin1String delim1( "--__--__--\n\nMessage:" ); + const QLatin1String delim2( "--__--__--\r\n\r\nMessage:" ); + const QLatin1String delimZ2( "--__--__--\n\n_____________" ); + const QLatin1String delimZ1( "--__--__--\r\n\r\n_____________" ); + QString partStr, digestHeaderStr; + int thisDelim = str.indexOf( delim1, Qt::CaseInsensitive ); + if ( thisDelim == -1 ) { + thisDelim = str.indexOf( delim2, Qt::CaseInsensitive ); + } + if ( thisDelim == -1 ) { + return false; + } - int nextDelim = str.indexOf( delim1, thisDelim+1, Qt::CaseInsensitive ); - if ( -1 == nextDelim ) { - nextDelim = str.indexOf( delim2, thisDelim+1, Qt::CaseInsensitive ); - } - if ( -1 == nextDelim ) { - nextDelim = str.indexOf( delimZ1, thisDelim+1, Qt::CaseInsensitive ); - } - if ( -1 == nextDelim ) { - nextDelim = str.indexOf( delimZ2, thisDelim+1, Qt::CaseInsensitive ); - } - if ( nextDelim < 0) { - return false; - } + int nextDelim = str.indexOf( delim1, thisDelim+1, Qt::CaseInsensitive ); + if ( -1 == nextDelim ) { + nextDelim = str.indexOf( delim2, thisDelim+1, Qt::CaseInsensitive ); + } + if ( -1 == nextDelim ) { + nextDelim = str.indexOf( delimZ1, thisDelim+1, Qt::CaseInsensitive ); + } + if ( -1 == nextDelim ) { + nextDelim = str.indexOf( delimZ2, thisDelim+1, Qt::CaseInsensitive ); + } + if ( nextDelim < 0) { + return false; + } - //if ( curNode->mRoot ) - // curNode = curNode->mRoot; + //if ( curNode->mRoot ) + // curNode = curNode->mRoot; - // at least one message found: build a mime tree - digestHeaderStr = QLatin1String("Content-Type: text/plain\nContent-Description: digest header\n\n"); - digestHeaderStr += str.mid( 0, thisDelim ); - createAndParseTempNode( mTopLevelContent, digestHeaderStr.toLatin1(), "Digest Header" ); - //mReader->queueHtml("


"); - // temporarily change curent node's Content-Type - // to get our embedded RfC822 messages properly inserted - curNode->contentType()->setMimeType( "multipart/digest" ); - while( -1 < nextDelim ){ - int thisEoL = str.indexOf(QLatin1String("\nMessage:"), thisDelim, Qt::CaseInsensitive ); - if ( -1 < thisEoL ) - thisDelim = thisEoL+1; - else{ - thisEoL = str.indexOf(QLatin1String("\n_____________"), thisDelim, Qt::CaseInsensitive ); - if ( -1 < thisEoL ) - thisDelim = thisEoL+1; - } - thisEoL = str.indexOf( QLatin1Char('\n'), thisDelim ); - if ( -1 < thisEoL ) - thisDelim = thisEoL+1; - else - thisDelim = thisDelim+1; - //while( thisDelim < cstr.size() && '\n' == cstr[thisDelim] ) - // ++thisDelim; - - partStr = QLatin1String("Content-Type: message/rfc822\nContent-Description: embedded message\n\n"); - partStr += QLatin1String("Content-Type: text/plain\n"); - partStr += str.mid( thisDelim, nextDelim-thisDelim ); - QString subject = QString::fromLatin1("embedded message"); - QString subSearch = QString::fromLatin1("\nSubject:"); - int subPos = partStr.indexOf(subSearch, 0, Qt::CaseInsensitive ); - if ( -1 < subPos ){ - subject = partStr.mid(subPos+subSearch.length()); - thisEoL = subject.indexOf(QLatin1Char('\n')); - if ( -1 < thisEoL ) - subject.truncate( thisEoL ); - } - kDebug() << " embedded message found: \"" << subject; - createAndParseTempNode( mTopLevelContent, partStr.toLatin1(), subject.toLatin1() ); + // at least one message found: build a mime tree + digestHeaderStr = QLatin1String("Content-Type: text/plain\nContent-Description: digest header\n\n"); + digestHeaderStr += str.mid( 0, thisDelim ); + createAndParseTempNode( mTopLevelContent, digestHeaderStr.toLatin1(), "Digest Header" ); //mReader->queueHtml("


"); - thisDelim = nextDelim+1; - nextDelim = str.indexOf(delim1, thisDelim, Qt::CaseInsensitive ); - if ( -1 == nextDelim ) - nextDelim = str.indexOf(delim2, thisDelim, Qt::CaseInsensitive); - if ( -1 == nextDelim ) - nextDelim = str.indexOf(delimZ1, thisDelim, Qt::CaseInsensitive); - if ( -1 == nextDelim ) - nextDelim = str.indexOf(delimZ2, thisDelim, Qt::CaseInsensitive); - } - // reset curent node's Content-Type - curNode->contentType()->setMimeType( "text/plain" ); - int thisEoL = str.indexOf( QLatin1String("_____________"), thisDelim ); - if ( -1 < thisEoL ){ - thisDelim = thisEoL; - thisEoL = str.indexOf( QLatin1Char('\n'), thisDelim ); - if ( -1 < thisEoL ) - thisDelim = thisEoL+1; - } - else - thisDelim = thisDelim+1; - partStr = QLatin1String("Content-Type: text/plain\nContent-Description: digest footer\n\n"); - partStr += str.mid( thisDelim ); - createAndParseTempNode( mTopLevelContent, partStr.toLatin1(), "Digest Footer" ); - return true; + // temporarily change curent node's Content-Type + // to get our embedded RfC822 messages properly inserted + curNode->contentType()->setMimeType( "multipart/digest" ); + while( -1 < nextDelim ){ + int thisEoL = str.indexOf(QLatin1String("\nMessage:"), thisDelim, Qt::CaseInsensitive ); + if ( -1 < thisEoL ) + thisDelim = thisEoL+1; + else{ + thisEoL = str.indexOf(QLatin1String("\n_____________"), thisDelim, Qt::CaseInsensitive ); + if ( -1 < thisEoL ) + thisDelim = thisEoL+1; + } + thisEoL = str.indexOf( QLatin1Char('\n'), thisDelim ); + if ( -1 < thisEoL ) + thisDelim = thisEoL+1; + else + thisDelim = thisDelim+1; + //while( thisDelim < cstr.size() && '\n' == cstr[thisDelim] ) + // ++thisDelim; + + partStr = QLatin1String("Content-Type: message/rfc822\nContent-Description: embedded message\n\n"); + partStr += QLatin1String("Content-Type: text/plain\n"); + partStr += str.mid( thisDelim, nextDelim-thisDelim ); + QString subject = QString::fromLatin1("embedded message"); + QString subSearch = QString::fromLatin1("\nSubject:"); + int subPos = partStr.indexOf(subSearch, 0, Qt::CaseInsensitive ); + if ( -1 < subPos ){ + subject = partStr.mid(subPos+subSearch.length()); + thisEoL = subject.indexOf(QLatin1Char('\n')); + if ( -1 < thisEoL ) + subject.truncate( thisEoL ); + } + kDebug() << " embedded message found: \"" << subject; + createAndParseTempNode( mTopLevelContent, partStr.toLatin1(), subject.toLatin1() ); + //mReader->queueHtml("


"); + thisDelim = nextDelim+1; + nextDelim = str.indexOf(delim1, thisDelim, Qt::CaseInsensitive ); + if ( -1 == nextDelim ) + nextDelim = str.indexOf(delim2, thisDelim, Qt::CaseInsensitive); + if ( -1 == nextDelim ) + nextDelim = str.indexOf(delimZ1, thisDelim, Qt::CaseInsensitive); + if ( -1 == nextDelim ) + nextDelim = str.indexOf(delimZ2, thisDelim, Qt::CaseInsensitive); + } + // reset curent node's Content-Type + curNode->contentType()->setMimeType( "text/plain" ); + int thisEoL = str.indexOf( QLatin1String("_____________"), thisDelim ); + if ( -1 < thisEoL ){ + thisDelim = thisEoL; + thisEoL = str.indexOf( QLatin1Char('\n'), thisDelim ); + if ( -1 < thisEoL ) + thisDelim = thisEoL+1; + } + else + thisDelim = thisDelim+1; + partStr = QLatin1String("Content-Type: text/plain\nContent-Description: digest footer\n\n"); + partStr += str.mid( thisDelim ); + createAndParseTempNode( mTopLevelContent, partStr.toLatin1(), "Digest Footer" ); + return true; } void ObjectTreeParser::extractNodeInfos( KMime::Content *curNode, bool isFirstTextPart ) { - mRawDecryptedBody = curNode->decodedContent(); - if ( isFirstTextPart ) { - mPlainTextContent += curNode->decodedText(); - mPlainTextContentCharset += NodeHelper::charset( curNode ); - } + mRawDecryptedBody = curNode->decodedContent(); + if ( isFirstTextPart ) { + mPlainTextContent += curNode->decodedText(); + mPlainTextContentCharset += NodeHelper::charset( curNode ); + } } - + bool ObjectTreeParser::processTextPlainSubtype( KMime::Content *curNode, ProcessResult & result ) { - const bool isFirstTextPart = ( curNode->topLevel()->textContent() == curNode ); - - if ( !isFirstTextPart && attachmentStrategy()->defaultDisplay( curNode ) != AttachmentStrategy::Inline && - !showOnlyOneMimePart() ) - return false; - - extractNodeInfos( curNode, isFirstTextPart ); - - QString label = NodeHelper::fileName( curNode ); + const bool isFirstTextPart = ( curNode->topLevel()->textContent() == curNode ); - const bool bDrawFrame = !isFirstTextPart - && !showOnlyOneMimePart() - && !label.isEmpty(); - if ( bDrawFrame && htmlWriter()) { - label = StringUtil::quoteHtmlChars( label, true ); - - const QString comment = - StringUtil::quoteHtmlChars( curNode->contentDescription()->asUnicodeString(), true ); - - const QString fileName; - mNodeHelper->writeNodeToTempFile( curNode ); - const QString dir = QApplication::isRightToLeft() ? QLatin1String("rtl") : QLatin1String("ltr") ; - - QString htmlStr = QLatin1String("" - "
"); - if ( !fileName.isEmpty() ) - htmlStr += QLatin1String("asHREF( curNode, QLatin1String("body") ) + QLatin1String("\">") - + label + QLatin1String(""); - else - htmlStr += label; - if ( !comment.isEmpty() ) - htmlStr += QLatin1String("
") + comment; - htmlStr += QLatin1String("
"); - - htmlWriter()->queue( htmlStr ); - } - // process old style not-multipart Mailman messages to - // enable verification of the embedded messages' signatures - if ( !isMailmanMessage( curNode ) || - !processMailmanMessage( curNode ) ) { - const QString oldPlainText = mPlainTextContent; - writeBodyString( mRawDecryptedBody, NodeHelper::fromAsString( curNode ), - codecFor( curNode ), result, !bDrawFrame ); - - // Revert changes to mPlainTextContent made by writeBodyString if this is not the first - // text part. The plain text content shall not contain any text/plain attachment, as it is content - // of the main text node. - if ( !isFirstTextPart ) { - mPlainTextContent = oldPlainText; - } - mNodeHelper->setNodeDisplayedEmbedded( curNode, true ); - } - if( bDrawFrame && htmlWriter() ) { - htmlWriter()->queue( QLatin1String("
") ); - } + if ( !isFirstTextPart && attachmentStrategy()->defaultDisplay( curNode ) != AttachmentStrategy::Inline && + !showOnlyOneMimePart() ) + return false; + + extractNodeInfos( curNode, isFirstTextPart ); + + QString label = NodeHelper::fileName( curNode ); + + const bool bDrawFrame = !isFirstTextPart + && !showOnlyOneMimePart() + && !label.isEmpty(); + if ( bDrawFrame && htmlWriter()) { + label = StringUtil::quoteHtmlChars( label, true ); + + const QString comment = + StringUtil::quoteHtmlChars( curNode->contentDescription()->asUnicodeString(), true ); + + const QString fileName; + mNodeHelper->writeNodeToTempFile( curNode ); + const QString dir = QApplication::isRightToLeft() ? QLatin1String("rtl") : QLatin1String("ltr") ; + + QString htmlStr = QLatin1String("" + "
"); + if ( !fileName.isEmpty() ) + htmlStr += QLatin1String("asHREF( curNode, QLatin1String("body") ) + QLatin1String("\">") + + label + QLatin1String(""); + else + htmlStr += label; + if ( !comment.isEmpty() ) + htmlStr += QLatin1String("
") + comment; + htmlStr += QLatin1String("
"); + + htmlWriter()->queue( htmlStr ); + } + // process old style not-multipart Mailman messages to + // enable verification of the embedded messages' signatures + if ( !isMailmanMessage( curNode ) || + !processMailmanMessage( curNode ) ) { + const QString oldPlainText = mPlainTextContent; + writeBodyString( mRawDecryptedBody, NodeHelper::fromAsString( curNode ), + codecFor( curNode ), result, !bDrawFrame ); + + // Revert changes to mPlainTextContent made by writeBodyString if this is not the first + // text part. The plain text content shall not contain any text/plain attachment, as it is content + // of the main text node. + if ( !isFirstTextPart ) { + mPlainTextContent = oldPlainText; + } + mNodeHelper->setNodeDisplayedEmbedded( curNode, true ); + } + if( bDrawFrame && htmlWriter() ) { + htmlWriter()->queue( QLatin1String("
") ); + } - return true; + return true; } void ObjectTreeParser::stdChildHandling( KMime::Content * child ) { - if ( !child ) - return; + if ( !child ) + return; - ObjectTreeParser otp( *this ); - otp.setShowOnlyOneMimePart( false ); - otp.parseObjectTreeInternal( child ); - copyContentFrom( &otp ); + ObjectTreeParser otp( *this ); + otp.setShowOnlyOneMimePart( false ); + otp.parseObjectTreeInternal( child ); + copyContentFrom( &otp ); } QString ObjectTreeParser::defaultToltecReplacementText() { - return i18n( "This message is a Toltec Groupware object, it can only be viewed with " - "Microsoft Outlook in combination with the Toltec connector." ); + return i18n( "This message is a Toltec Groupware object, it can only be viewed with " + "Microsoft Outlook in combination with the Toltec connector." ); } bool ObjectTreeParser::processToltecMail( KMime::Content *node ) { - if ( !node || !htmlWriter() || !GlobalSettings::self()->showToltecReplacementText() || - !NodeHelper::isToltecMessage( node ) || mShowRawToltecMail ) - return false; - - htmlWriter()->queue( GlobalSettings::self()->toltecReplacementText() ); - htmlWriter()->queue( QLatin1String("

") + - i18n( "Show Raw Message" ) + QLatin1String("") ); - return true; + if ( !node || !htmlWriter() || !GlobalSettings::self()->showToltecReplacementText() || + !NodeHelper::isToltecMessage( node ) || mShowRawToltecMail ) + return false; + + htmlWriter()->queue( GlobalSettings::self()->toltecReplacementText() ); + htmlWriter()->queue( QLatin1String("

") + + i18n( "Show Raw Message" ) + QLatin1String("") ); + return true; } bool ObjectTreeParser::processMultiPartMixedSubtype( KMime::Content * node, ProcessResult & ) { - if ( processToltecMail( node ) ) { - return true; - } + if ( processToltecMail( node ) ) { + return true; + } - KMime::Content * child = MessageCore::NodeHelper::firstChild( node ); - if ( !child ) - return false; + KMime::Content * child = MessageCore::NodeHelper::firstChild( node ); + if ( !child ) + return false; - // normal treatment of the parts in the mp/mixed container - stdChildHandling( child ); - return true; + // normal treatment of the parts in the mp/mixed container + stdChildHandling( child ); + return true; } bool ObjectTreeParser::processMultiPartAlternativeSubtype( KMime::Content * node, ProcessResult & ) { - KMime::Content * child = MessageCore::NodeHelper::firstChild( node ); - if ( !child ) - return false; - - KMime::Content* dataHtml = findType( child, "text/html", false, true ); - KMime::Content* dataPlain = findType( child, "text/plain", false, true ); - - if ( !dataHtml ) { - // If we didn't find the HTML part as the first child of the multipart/alternative, it might - // be that this is a HTML message with images, and text/plain and multipart/related are the - // immediate children of this multipart/alternative node. - // In this case, the HTML node is a child of multipart/related. - dataHtml = findType( child, "multipart/related", false, true ); - - // Still not found? Stupid apple mail actually puts the attachments inside of the - // multipart/alternative, which is wrong. Therefore we also have to look for multipart/mixed - // here. - // Do this only when prefering HTML mail, though, since otherwise the attachments are hidden - // when displaying plain text. - if ( !dataHtml && mSource->htmlMail() ) { - dataHtml = findType( child, "multipart/mixed", false, true ); + KMime::Content * child = MessageCore::NodeHelper::firstChild( node ); + if ( !child ) + return false; + + KMime::Content* dataHtml = findType( child, "text/html", false, true ); + KMime::Content* dataPlain = findType( child, "text/plain", false, true ); + + if ( !dataHtml ) { + // If we didn't find the HTML part as the first child of the multipart/alternative, it might + // be that this is a HTML message with images, and text/plain and multipart/related are the + // immediate children of this multipart/alternative node. + // In this case, the HTML node is a child of multipart/related. + dataHtml = findType( child, "multipart/related", false, true ); + + // Still not found? Stupid apple mail actually puts the attachments inside of the + // multipart/alternative, which is wrong. Therefore we also have to look for multipart/mixed + // here. + // Do this only when prefering HTML mail, though, since otherwise the attachments are hidden + // when displaying plain text. + if ( !dataHtml && mSource->htmlMail() ) { + dataHtml = findType( child, "multipart/mixed", false, true ); + } } - } - // If there is no HTML writer, process both the HTML and the plain text nodes, as we're collecting - // the plainTextContent and the htmlContent - if ( !htmlWriter() ) { - if ( dataPlain ) { - stdChildHandling( dataPlain ); + // If there is no HTML writer, process both the HTML and the plain text nodes, as we're collecting + // the plainTextContent and the htmlContent + if ( !htmlWriter() ) { + if ( dataPlain ) { + stdChildHandling( dataPlain ); + } + if ( dataHtml ) { + stdChildHandling( dataHtml ); + } + return true; } - if ( dataHtml ) { - stdChildHandling( dataHtml ); + + if ( ( mSource->htmlMail() && dataHtml) || + (dataHtml && dataPlain && dataPlain->body().isEmpty()) ) { + if ( dataPlain ) + mNodeHelper->setNodeProcessed( dataPlain, false); + stdChildHandling( dataHtml ); + mSource->setHtmlMode( Util::MultipartHtml ); + return true; } - return true; - } - if ( ( mSource->htmlMail() && dataHtml) || - (dataHtml && dataPlain && dataPlain->body().isEmpty()) ) { - if ( dataPlain ) - mNodeHelper->setNodeProcessed( dataPlain, false); - stdChildHandling( dataHtml ); - mSource->setHtmlMode( Util::MultipartHtml ); - return true; - } + if ( !htmlWriter() || (!mSource->htmlMail() && dataPlain) ) { + mNodeHelper->setNodeProcessed( dataHtml, false ); + stdChildHandling( dataPlain ); + mSource->setHtmlMode( Util::MultipartPlain ); + return true; + } - if ( !htmlWriter() || (!mSource->htmlMail() && dataPlain) ) { - mNodeHelper->setNodeProcessed( dataHtml, false ); - stdChildHandling( dataPlain ); - mSource->setHtmlMode( Util::MultipartPlain ); + stdChildHandling( child ); return true; - } - - stdChildHandling( child ); - return true; } bool ObjectTreeParser::processMultiPartDigestSubtype( KMime::Content * node, ProcessResult & result ) { - return processMultiPartMixedSubtype( node, result ); + return processMultiPartMixedSubtype( node, result ); } bool ObjectTreeParser::processMultiPartParallelSubtype( KMime::Content * node, ProcessResult & result ) { - return processMultiPartMixedSubtype( node, result ); + return processMultiPartMixedSubtype( node, result ); } bool ObjectTreeParser::processMultiPartSignedSubtype( KMime::Content * node, ProcessResult & ) { - KMime::Content * child = MessageCore::NodeHelper::firstChild( node ); - if ( node->contents().size() != 2 ) { - kDebug() << "mulitpart/signed must have exactly two child parts!" << endl - << "processing as multipart/mixed"; - if ( child ) - stdChildHandling( child ); - return child; - } - - KMime::Content * signedData = child; - assert( signedData ); + KMime::Content * child = MessageCore::NodeHelper::firstChild( node ); + if ( node->contents().size() != 2 ) { + kDebug() << "mulitpart/signed must have exactly two child parts!" << endl + << "processing as multipart/mixed"; + if ( child ) + stdChildHandling( child ); + return child; + } - KMime::Content * signature = node->contents().at(1); - assert( signature ); + KMime::Content * signedData = child; + assert( signedData ); - mNodeHelper->setNodeProcessed( signature, true); + KMime::Content * signature = node->contents().at(1); + assert( signature ); - if ( !includeSignatures() ) { - stdChildHandling( signedData ); - return true; - } + mNodeHelper->setNodeProcessed( signature, true); - QString protocolContentType = node->contentType()->parameter( QLatin1String("protocol") ).toLower(); - const QString signatureContentType = QLatin1String(signature->contentType()->mimeType().toLower()); - if ( protocolContentType.isEmpty() ) { - kWarning() << "Message doesn't set the protocol for the multipart/signed content-type, " - "using content-type of the signature:" << signatureContentType; - protocolContentType = signatureContentType; - } + if ( !includeSignatures() ) { + stdChildHandling( signedData ); + return true; + } - const Kleo::CryptoBackend::Protocol *protocol = 0; - if ( protocolContentType == QLatin1String( "application/pkcs7-signature" ) || - protocolContentType == QLatin1String( "application/x-pkcs7-signature" ) ) - protocol = Kleo::CryptoBackendFactory::instance()->smime(); - else if ( protocolContentType == QLatin1String( "application/pgp-signature" ) || - protocolContentType == QLatin1String( "application/x-pgp-signature" ) ) - protocol = Kleo::CryptoBackendFactory::instance()->openpgp(); - - if ( !protocol ) { - mNodeHelper->setNodeProcessed( signature, true ); - stdChildHandling( signedData ); - return true; - } + QString protocolContentType = node->contentType()->parameter( QLatin1String("protocol") ).toLower(); + const QString signatureContentType = QLatin1String(signature->contentType()->mimeType().toLower()); + if ( protocolContentType.isEmpty() ) { + kWarning() << "Message doesn't set the protocol for the multipart/signed content-type, " + "using content-type of the signature:" << signatureContentType; + protocolContentType = signatureContentType; + } + + const Kleo::CryptoBackend::Protocol *protocol = 0; + if ( protocolContentType == QLatin1String( "application/pkcs7-signature" ) || + protocolContentType == QLatin1String( "application/x-pkcs7-signature" ) ) + protocol = Kleo::CryptoBackendFactory::instance()->smime(); + else if ( protocolContentType == QLatin1String( "application/pgp-signature" ) || + protocolContentType == QLatin1String( "application/x-pgp-signature" ) ) + protocol = Kleo::CryptoBackendFactory::instance()->openpgp(); + + if ( !protocol ) { + mNodeHelper->setNodeProcessed( signature, true ); + stdChildHandling( signedData ); + return true; + } - CryptoProtocolSaver saver( this, protocol ); - mNodeHelper->setSignatureState( node, KMMsgFullySigned); + CryptoProtocolSaver saver( this, protocol ); + mNodeHelper->setSignatureState( node, KMMsgFullySigned); - writeOpaqueOrMultipartSignedData( signedData, *signature, - NodeHelper::fromAsString( node ) ); - return true; + writeOpaqueOrMultipartSignedData( signedData, *signature, + NodeHelper::fromAsString( node ) ); + return true; } bool ObjectTreeParser::processMultiPartEncryptedSubtype( KMime::Content * node, ProcessResult & result ) { - KMime::Content * child = MessageCore::NodeHelper::firstChild( node ); - if ( !child ) - return false; + KMime::Content * child = MessageCore::NodeHelper::firstChild( node ); + if ( !child ) + return false; - if ( keepEncryptions() ) { - mNodeHelper->setEncryptionState( node, KMMsgFullyEncrypted ); - const QByteArray cstr = node->decodedContent(); - if ( htmlWriter() ) { - writeBodyString( cstr, NodeHelper::fromAsString( node ), - codecFor( node ), result, false ); + if ( keepEncryptions() ) { + mNodeHelper->setEncryptionState( node, KMMsgFullyEncrypted ); + const QByteArray cstr = node->decodedContent(); + if ( htmlWriter() ) { + writeBodyString( cstr, NodeHelper::fromAsString( node ), + codecFor( node ), result, false ); + } + mRawDecryptedBody += cstr; + return true; } - mRawDecryptedBody += cstr; - return true; - } - const Kleo::CryptoBackend::Protocol * useThisCryptProto = 0; + const Kleo::CryptoBackend::Protocol * useThisCryptProto = 0; - /* + /* ATTENTION: This code is to be replaced by the new 'auto-detect' feature. -------------------------------------- */ - KMime::Content* data = findType( child, "application/octet-stream", false, true ); - if ( data ) { - useThisCryptProto = Kleo::CryptoBackendFactory::instance()->openpgp(); - } - if ( !data ) { - data = findType( child, "application/pkcs7-mime", false, true ); + KMime::Content* data = findType( child, "application/octet-stream", false, true ); if ( data ) { - useThisCryptProto = Kleo::CryptoBackendFactory::instance()->smime(); + useThisCryptProto = Kleo::CryptoBackendFactory::instance()->openpgp(); } - } - /* + if ( !data ) { + data = findType( child, "application/pkcs7-mime", false, true ); + if ( data ) { + useThisCryptProto = Kleo::CryptoBackendFactory::instance()->smime(); + } + } + /* --------------------------------------------------------------------------------------------------------------- */ - if ( !data ) { - stdChildHandling( child ); - return true; - } - - CryptoProtocolSaver cpws( this, useThisCryptProto ); + if ( !data ) { + stdChildHandling( child ); + return true; + } - KMime::Content * dataChild = MessageCore::NodeHelper::firstChild( data ); - if ( dataChild ) { - stdChildHandling( dataChild ); - return true; - } + CryptoProtocolSaver cpws( this, useThisCryptProto ); - mNodeHelper->setEncryptionState( node, KMMsgFullyEncrypted ); + KMime::Content * dataChild = MessageCore::NodeHelper::firstChild( data ); + if ( dataChild ) { + stdChildHandling( dataChild ); + return true; + } - if ( !mSource->decryptMessage() ) { - writeDeferredDecryptionBlock(); - mNodeHelper->setNodeProcessed( data, false );// Set the data node to done to prevent it from being processed - return true; - } + mNodeHelper->setEncryptionState( node, KMMsgFullyEncrypted ); - PartMetaData messagePart; - // if we already have a decrypted node for this encrypted node, don't do the decryption again - if ( KMime::Content * newNode = mNodeHelper->decryptedNodeForContent( data ) ) - { -// if( NodeHelper::nodeProcessed( data ) ) - ObjectTreeParser otp( this ); - otp.parseObjectTreeInternal( newNode ); - copyContentFrom( &otp ); - messagePart = mNodeHelper->partMetaData( node ); - } else { - QByteArray decryptedData; - bool signatureFound; - std::vector signatures; - bool passphraseError; - bool actuallyEncrypted = true; - bool decryptionStarted; - - bool bOkDecrypt = okDecryptMIME( *data, - decryptedData, - signatureFound, - signatures, - true, - passphraseError, - actuallyEncrypted, - decryptionStarted, - messagePart ); - //kDebug() << "decrypted, signed?:" << signatureFound; - - if ( decryptionStarted ) { - writeDecryptionInProgressBlock(); - return true; - } - - mNodeHelper->setNodeProcessed( data, false ); // Set the data node to done to prevent it from being processed - - // paint the frame - if ( htmlWriter() ) { - messagePart.isDecryptable = bOkDecrypt; - messagePart.isEncrypted = true; - messagePart.isSigned = false; - htmlWriter()->queue( writeSigstatHeader( messagePart, - cryptoProtocol(), - NodeHelper::fromAsString( node ) ) ); - } - - if ( bOkDecrypt ) { - // Note: Multipart/Encrypted might also be signed - // without encapsulating a nicely formatted - // ~~~~~~~ Multipart/Signed part. - // (see RFC 3156 --> 6.2) - // In this case we paint a _2nd_ frame inside the - // encryption frame, but we do _not_ show a respective - // encapsulated MIME part in the Mime Tree Viewer - // since we do want to show the _true_ structure of the - // message there - not the structure that the sender's - // MUA 'should' have sent. :-D (khz, 12.09.2002) - // - if ( signatureFound ) { - writeOpaqueOrMultipartSignedData( 0, - *node, - NodeHelper::fromAsString( node ), - false, - &decryptedData, - signatures, - false ); - mNodeHelper->setSignatureState( node, KMMsgFullySigned); - //kDebug() << "setting FULLY SIGNED to:" << node; - } else { - decryptedData = KMime::CRLFtoLF( decryptedData ); //KMime works with LF only inside insertAndParseNewChildNode + if ( !mSource->decryptMessage() ) { + writeDeferredDecryptionBlock(); + mNodeHelper->setNodeProcessed( data, false );// Set the data node to done to prevent it from being processed + return true; + } - createAndParseTempNode( node, decryptedData.constData(),"encrypted data" ); - } + PartMetaData messagePart; + // if we already have a decrypted node for this encrypted node, don't do the decryption again + if ( KMime::Content * newNode = mNodeHelper->decryptedNodeForContent( data ) ) + { + // if( NodeHelper::nodeProcessed( data ) ) + ObjectTreeParser otp( this ); + otp.parseObjectTreeInternal( newNode ); + copyContentFrom( &otp ); + messagePart = mNodeHelper->partMetaData( node ); } else { - mRawDecryptedBody += decryptedData; - if ( htmlWriter() ) { - // print the error message that was returned in decryptedData - // (utf8-encoded) - htmlWriter()->queue( QString::fromUtf8( decryptedData.data() ) ); - } - } + QByteArray decryptedData; + bool signatureFound; + std::vector signatures; + bool passphraseError; + bool actuallyEncrypted = true; + bool decryptionStarted; + bool bOkDecrypt = okDecryptMIME( *data, + decryptedData, + signatureFound, + signatures, + true, + passphraseError, + actuallyEncrypted, + decryptionStarted, + messagePart ); + //kDebug() << "decrypted, signed?:" << signatureFound; - mNodeHelper->setPartMetaData( node, messagePart ); - } + if ( decryptionStarted ) { + writeDecryptionInProgressBlock(); + return true; + } - if ( htmlWriter() ) - htmlWriter()->queue( writeSigstatFooter( messagePart ) ); - return true; + mNodeHelper->setNodeProcessed( data, false ); // Set the data node to done to prevent it from being processed + + // paint the frame + if ( htmlWriter() ) { + messagePart.isDecryptable = bOkDecrypt; + messagePart.isEncrypted = true; + messagePart.isSigned = false; + htmlWriter()->queue( writeSigstatHeader( messagePart, + cryptoProtocol(), + NodeHelper::fromAsString( node ) ) ); + } + + if ( bOkDecrypt ) { + // Note: Multipart/Encrypted might also be signed + // without encapsulating a nicely formatted + // ~~~~~~~ Multipart/Signed part. + // (see RFC 3156 --> 6.2) + // In this case we paint a _2nd_ frame inside the + // encryption frame, but we do _not_ show a respective + // encapsulated MIME part in the Mime Tree Viewer + // since we do want to show the _true_ structure of the + // message there - not the structure that the sender's + // MUA 'should' have sent. :-D (khz, 12.09.2002) + // + if ( signatureFound ) { + writeOpaqueOrMultipartSignedData( 0, + *node, + NodeHelper::fromAsString( node ), + false, + &decryptedData, + signatures, + false ); + mNodeHelper->setSignatureState( node, KMMsgFullySigned); + //kDebug() << "setting FULLY SIGNED to:" << node; + } else { + decryptedData = KMime::CRLFtoLF( decryptedData ); //KMime works with LF only inside insertAndParseNewChildNode + + createAndParseTempNode( node, decryptedData.constData(),"encrypted data" ); + } + } else { + mRawDecryptedBody += decryptedData; + if ( htmlWriter() ) { + // print the error message that was returned in decryptedData + // (utf8-encoded) + htmlWriter()->queue( QString::fromUtf8( decryptedData.data() ) ); + } + } + + + mNodeHelper->setPartMetaData( node, messagePart ); + } + + if ( htmlWriter() ) + htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + return true; } bool ObjectTreeParser::processMessageRfc822Subtype( KMime::Content * node, ProcessResult & ) { - if ( htmlWriter() && !attachmentStrategy()->inlineNestedMessages() && !showOnlyOneMimePart() ) - return false; + if ( htmlWriter() && !attachmentStrategy()->inlineNestedMessages() && !showOnlyOneMimePart() ) + return false; - PartMetaData messagePart; - messagePart.isEncrypted = false; - messagePart.isSigned = false; - messagePart.isEncapsulatedRfc822Message = true; - - KMime::Message::Ptr message = node->bodyAsMessage(); - if ( !message ) { - kWarning() << "Node is of type message/rfc822 but doesn't have a message!"; - } - - if ( htmlWriter() && message ) { - - // The link to "Encapsulated message" is clickable, therefore the temp file needs to exists, - // since the user can click the link and expect to have normal attachment operations there. - mNodeHelper->writeNodeToTempFile( message.get() ); + PartMetaData messagePart; + messagePart.isEncrypted = false; + messagePart.isSigned = false; + messagePart.isEncapsulatedRfc822Message = true; - // Paint the frame header - htmlWriter()->queue( writeSigstatHeader( messagePart, - cryptoProtocol(), - message->from()->asUnicodeString(), - message.get() ) ); + KMime::Message::Ptr message = node->bodyAsMessage(); + if ( !message ) { + kWarning() << "Node is of type message/rfc822 but doesn't have a message!"; + } - // Paint the message header - htmlWriter()->queue( mSource->createMessageHeader( message.get() ) ); + if ( htmlWriter() && message ) { - // Process the message, i.e. paint it by processing it with an OTP - ObjectTreeParser otp( this ); - otp.parseObjectTreeInternal( message.get() ); + // The link to "Encapsulated message" is clickable, therefore the temp file needs to exists, + // since the user can click the link and expect to have normal attachment operations there. + mNodeHelper->writeNodeToTempFile( message.get() ); - // Don't add the resulting textual content to our textual content here. - // That is unwanted when inline forwarding a message, since the encapsulated message will - // already be in the forward message as attachment, so don't duplicate the textual content - // by adding it to the inline body as well + // Paint the frame header + htmlWriter()->queue( writeSigstatHeader( messagePart, + cryptoProtocol(), + message->from()->asUnicodeString(), + message.get() ) ); + + // Paint the message header + htmlWriter()->queue( mSource->createMessageHeader( message.get() ) ); + + // Process the message, i.e. paint it by processing it with an OTP + ObjectTreeParser otp( this ); + otp.parseObjectTreeInternal( message.get() ); + + // Don't add the resulting textual content to our textual content here. + // That is unwanted when inline forwarding a message, since the encapsulated message will + // already be in the forward message as attachment, so don't duplicate the textual content + // by adding it to the inline body as well - // Paint the frame footer - htmlWriter()->queue( writeSigstatFooter( messagePart ) ); - } + // Paint the frame footer + htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + } - mNodeHelper->setNodeDisplayedEmbedded( node, true ); - mNodeHelper->setPartMetaData( node, messagePart ); + mNodeHelper->setNodeDisplayedEmbedded( node, true ); + mNodeHelper->setPartMetaData( node, messagePart ); - return true; + return true; } bool ObjectTreeParser::processApplicationOctetStreamSubtype( KMime::Content * node, ProcessResult & result ) { - if ( KMime::Content * child = mNodeHelper->decryptedNodeForContent( node ) ) { - ObjectTreeParser otp( this ); - otp.parseObjectTreeInternal( child ); - copyContentFrom( &otp ); - return true; - } + if ( KMime::Content * child = mNodeHelper->decryptedNodeForContent( node ) ) { + ObjectTreeParser otp( this ); + otp.parseObjectTreeInternal( child ); + copyContentFrom( &otp ); + return true; + } - const Kleo::CryptoBackend::Protocol* oldUseThisCryptPlug = cryptoProtocol(); - if ( node->parent() - && node->parent()->contentType()->mimeType() == "multipart/encrypted" ) { - mNodeHelper->setEncryptionState( node, KMMsgFullyEncrypted ); - if ( keepEncryptions() ) { - const QByteArray cstr = node->decodedContent(); - if ( htmlWriter() ) { - writeBodyString( cstr, NodeHelper::fromAsString( node ), - codecFor( node ), result, false ); - } - mRawDecryptedBody += cstr; - } else if ( !mSource->decryptMessage() ) { - writeDeferredDecryptionBlock(); - } else { - /* + const Kleo::CryptoBackend::Protocol* oldUseThisCryptPlug = cryptoProtocol(); + if ( node->parent() + && node->parent()->contentType()->mimeType() == "multipart/encrypted" ) { + mNodeHelper->setEncryptionState( node, KMMsgFullyEncrypted ); + if ( keepEncryptions() ) { + const QByteArray cstr = node->decodedContent(); + if ( htmlWriter() ) { + writeBodyString( cstr, NodeHelper::fromAsString( node ), + codecFor( node ), result, false ); + } + mRawDecryptedBody += cstr; + } else if ( !mSource->decryptMessage() ) { + writeDeferredDecryptionBlock(); + } else { + /* ATTENTION: This code is to be replaced by the planned 'auto-detect' feature. */ - PartMetaData messagePart; - setCryptoProtocol( Kleo::CryptoBackendFactory::instance()->openpgp() ); - QByteArray decryptedData; - bool signatureFound; - std::vector signatures; - bool passphraseError; - bool actuallyEncrypted = true; - bool decryptionStarted; - - bool bOkDecrypt = okDecryptMIME( *node, - decryptedData, - signatureFound, - signatures, - true, - passphraseError, - actuallyEncrypted, - decryptionStarted, - messagePart ); + PartMetaData messagePart; + setCryptoProtocol( Kleo::CryptoBackendFactory::instance()->openpgp() ); + QByteArray decryptedData; + bool signatureFound; + std::vector signatures; + bool passphraseError; + bool actuallyEncrypted = true; + bool decryptionStarted; + + bool bOkDecrypt = okDecryptMIME( *node, + decryptedData, + signatureFound, + signatures, + true, + passphraseError, + actuallyEncrypted, + decryptionStarted, + messagePart ); + + if ( decryptionStarted ) { + writeDecryptionInProgressBlock(); + return true; + } - if ( decryptionStarted ) { - writeDecryptionInProgressBlock(); - return true; - } + // paint the frame + if ( htmlWriter() ) { + messagePart.isDecryptable = bOkDecrypt; + messagePart.isEncrypted = true; + messagePart.isSigned = false; + htmlWriter()->queue( writeSigstatHeader( messagePart, + cryptoProtocol(), + NodeHelper::fromAsString( node ) ) ); + } - // paint the frame - if ( htmlWriter() ) { - messagePart.isDecryptable = bOkDecrypt; - messagePart.isEncrypted = true; - messagePart.isSigned = false; - htmlWriter()->queue( writeSigstatHeader( messagePart, - cryptoProtocol(), - NodeHelper::fromAsString( node ) ) ); - } + if ( bOkDecrypt ) { + // fixing the missing attachments bug #1090-b + createAndParseTempNode( node, decryptedData.constData(), "encrypted data" ); + } else { + mRawDecryptedBody += decryptedData; + if ( htmlWriter() ) { + // print the error message that was returned in decryptedData + // (utf8-encoded) + htmlWriter()->queue( QString::fromUtf8( decryptedData.data() ) ); + } + } - if ( bOkDecrypt ) { - // fixing the missing attachments bug #1090-b - createAndParseTempNode( node, decryptedData.constData(), "encrypted data" ); - } else { - mRawDecryptedBody += decryptedData; - if ( htmlWriter() ) { - // print the error message that was returned in decryptedData - // (utf8-encoded) - htmlWriter()->queue( QString::fromUtf8( decryptedData.data() ) ); + if ( htmlWriter() ) + htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + mNodeHelper->setPartMetaData( node, messagePart ); } - } - - if ( htmlWriter() ) - htmlWriter()->queue( writeSigstatFooter( messagePart ) ); - mNodeHelper->setPartMetaData( node, messagePart ); + return true; } - return true; - } - setCryptoProtocol( oldUseThisCryptPlug ); - return false; + setCryptoProtocol( oldUseThisCryptPlug ); + return false; } bool ObjectTreeParser::processApplicationPkcs7MimeSubtype( KMime::Content * node, ProcessResult & result ) { - if ( KMime::Content * child = mNodeHelper->decryptedNodeForContent( node ) ) { - ObjectTreeParser otp( this ); - otp.parseObjectTreeInternal( child ); - copyContentFrom( &otp ); - return true; - } + if ( KMime::Content * child = mNodeHelper->decryptedNodeForContent( node ) ) { + ObjectTreeParser otp( this ); + otp.parseObjectTreeInternal( child ); + copyContentFrom( &otp ); + return true; + } - if ( node->head().isEmpty() ) - return false; + if ( node->head().isEmpty() ) + return false; - const Kleo::CryptoBackend::Protocol * smimeCrypto = Kleo::CryptoBackendFactory::instance()->smime(); - if ( !smimeCrypto ) - return false; + const Kleo::CryptoBackend::Protocol * smimeCrypto = Kleo::CryptoBackendFactory::instance()->smime(); + if ( !smimeCrypto ) + return false; - const QString smimeType = node->contentType()->parameter(QLatin1String("smime-type")).toLower(); + const QString smimeType = node->contentType()->parameter(QLatin1String("smime-type")).toLower(); - if ( smimeType == QLatin1String( "certs-only" ) ) { - result.setNeverDisplayInline( true ); - if ( !htmlWriter() ) - return false; + if ( smimeType == QLatin1String( "certs-only" ) ) { + result.setNeverDisplayInline( true ); + if ( !htmlWriter() ) + return false; - if ( !GlobalSettings::self()->autoImportKeys() ) - return false; + if ( !GlobalSettings::self()->autoImportKeys() ) + return false; - const QByteArray certData = node->decodedContent(); + const QByteArray certData = node->decodedContent(); - Kleo::ImportJob *import = smimeCrypto->importJob(); - KleoJobExecutor executor; - const GpgME::ImportResult res = executor.exec( import, certData ); - writeCertificateImportResult( res ); - return true; - } + Kleo::ImportJob *import = smimeCrypto->importJob(); + KleoJobExecutor executor; + const GpgME::ImportResult res = executor.exec( import, certData ); + writeCertificateImportResult( res ); + return true; + } - CryptoProtocolSaver cpws( this, smimeCrypto ); + CryptoProtocolSaver cpws( this, smimeCrypto ); - bool isSigned = ( smimeType == QLatin1String( "signed-data" ) ); - bool isEncrypted = ( smimeType == QLatin1String( "enveloped-data" ) ); + bool isSigned = ( smimeType == QLatin1String( "signed-data" ) ); + bool isEncrypted = ( smimeType == QLatin1String( "enveloped-data" ) ); - // Analyze "signTestNode" node to find/verify a signature. - // If zero this verification was successfully done after - // decrypting via recursion by insertAndParseNewChildNode(). - KMime::Content* signTestNode = isEncrypted ? 0 : node; - - - // We try decrypting the content - // if we either *know* that it is an encrypted message part - // or there is neither signed nor encrypted parameter. - if ( !isSigned ) { - if ( isEncrypted ) { - ;//kDebug() << "pkcs7 mime == S/MIME TYPE: enveloped (encrypted) data"; - } else { - ;//kDebug() << "pkcs7 mime - type unknown - enveloped (encrypted) data ?"; - } - QByteArray decryptedData; - PartMetaData messagePart; - messagePart.isEncrypted = true; - messagePart.isSigned = false; - bool signatureFound; - std::vector signatures; - bool passphraseError; - bool actuallyEncrypted = true; - bool decryptionStarted; + // Analyze "signTestNode" node to find/verify a signature. + // If zero this verification was successfully done after + // decrypting via recursion by insertAndParseNewChildNode(). + KMime::Content* signTestNode = isEncrypted ? 0 : node; - if ( !mSource->decryptMessage() ) { - writeDeferredDecryptionBlock(); - isEncrypted = true; - signTestNode = 0; // PENDING(marc) to be abs. sure, we'd need to have to look at the content - } else { - const bool bOkDecrypt = okDecryptMIME( *node, decryptedData, signatureFound, signatures, - false, passphraseError, actuallyEncrypted, - decryptionStarted, messagePart ); - //kDebug() << "PKCS7 found signature?" << signatureFound; - if ( decryptionStarted ) { - writeDecryptionInProgressBlock(); - return true; - } - if ( bOkDecrypt ) { - //kDebug() << "pkcs7 mime - encryption found - enveloped (encrypted) data !"; - isEncrypted = true; - mNodeHelper->setEncryptionState( node, KMMsgFullyEncrypted ); - if( signatureFound ) - mNodeHelper->setSignatureState( node, KMMsgFullySigned ); - signTestNode = 0; - // paint the frame - messagePart.isDecryptable = true; - if ( htmlWriter() ) - htmlWriter()->queue( writeSigstatHeader( messagePart, - cryptoProtocol(), - NodeHelper::fromAsString( node ) ) ); - createAndParseTempNode( node, decryptedData.constData(), "encrypted data" ); - if ( htmlWriter() ) - htmlWriter()->queue( writeSigstatFooter( messagePart ) ); - } else { - // decryption failed, which could be because the part was encrypted but - // decryption failed, or because we didn't know if it was encrypted, tried, - // and failed. If the message was not actually encrypted, we continue - // assuming it's signed - if ( passphraseError || ( smimeType.isEmpty() && actuallyEncrypted ) ) { - isEncrypted = true; - signTestNode = 0; + // We try decrypting the content + // if we either *know* that it is an encrypted message part + // or there is neither signed nor encrypted parameter. + if ( !isSigned ) { + if ( isEncrypted ) { + ;//kDebug() << "pkcs7 mime == S/MIME TYPE: enveloped (encrypted) data"; + } else { + ;//kDebug() << "pkcs7 mime - type unknown - enveloped (encrypted) data ?"; } + QByteArray decryptedData; + PartMetaData messagePart; + messagePart.isEncrypted = true; + messagePart.isSigned = false; + bool signatureFound; + std::vector signatures; + bool passphraseError; + bool actuallyEncrypted = true; + bool decryptionStarted; - if ( isEncrypted ) { - //kDebug() << "pkcs7 mime - ERROR: COULD NOT DECRYPT enveloped data !"; - // paint the frame - messagePart.isDecryptable = false; - if ( htmlWriter() ) { - htmlWriter()->queue( writeSigstatHeader( messagePart, - cryptoProtocol(), - NodeHelper::fromAsString( node ) ) ); - assert( mSource->decryptMessage() ); // handled above - writePartIcon( node ); - htmlWriter()->queue( writeSigstatFooter( messagePart ) ); - } + if ( !mSource->decryptMessage() ) { + writeDeferredDecryptionBlock(); + isEncrypted = true; + signTestNode = 0; // PENDING(marc) to be abs. sure, we'd need to have to look at the content } else { - //kDebug() << "pkcs7 mime - NO encryption found"; + const bool bOkDecrypt = okDecryptMIME( *node, decryptedData, signatureFound, signatures, + false, passphraseError, actuallyEncrypted, + decryptionStarted, messagePart ); + //kDebug() << "PKCS7 found signature?" << signatureFound; + if ( decryptionStarted ) { + writeDecryptionInProgressBlock(); + return true; + } + + if ( bOkDecrypt ) { + //kDebug() << "pkcs7 mime - encryption found - enveloped (encrypted) data !"; + isEncrypted = true; + mNodeHelper->setEncryptionState( node, KMMsgFullyEncrypted ); + if( signatureFound ) + mNodeHelper->setSignatureState( node, KMMsgFullySigned ); + signTestNode = 0; + // paint the frame + messagePart.isDecryptable = true; + if ( htmlWriter() ) + htmlWriter()->queue( writeSigstatHeader( messagePart, + cryptoProtocol(), + NodeHelper::fromAsString( node ) ) ); + createAndParseTempNode( node, decryptedData.constData(), "encrypted data" ); + if ( htmlWriter() ) + htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + } else { + // decryption failed, which could be because the part was encrypted but + // decryption failed, or because we didn't know if it was encrypted, tried, + // and failed. If the message was not actually encrypted, we continue + // assuming it's signed + if ( passphraseError || ( smimeType.isEmpty() && actuallyEncrypted ) ) { + isEncrypted = true; + signTestNode = 0; + } + + if ( isEncrypted ) { + //kDebug() << "pkcs7 mime - ERROR: COULD NOT DECRYPT enveloped data !"; + // paint the frame + messagePart.isDecryptable = false; + if ( htmlWriter() ) { + htmlWriter()->queue( writeSigstatHeader( messagePart, + cryptoProtocol(), + NodeHelper::fromAsString( node ) ) ); + assert( mSource->decryptMessage() ); // handled above + writePartIcon( node ); + htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + } + } else { + //kDebug() << "pkcs7 mime - NO encryption found"; + } + } } - } + if ( isEncrypted ) + mNodeHelper->setEncryptionState( node, KMMsgFullyEncrypted ); + mNodeHelper->setPartMetaData( node, messagePart ); } - if ( isEncrypted ) - mNodeHelper->setEncryptionState( node, KMMsgFullyEncrypted ); - mNodeHelper->setPartMetaData( node, messagePart ); - } - // We now try signature verification if necessarry. - if ( signTestNode ) { - if ( isSigned ) { - ;//kDebug() << "pkcs7 mime == S/MIME TYPE: opaque signed data"; - } else { - ;//kDebug() << "pkcs7 mime - type unknown - opaque signed data ?"; - } + // We now try signature verification if necessarry. + if ( signTestNode ) { + if ( isSigned ) { + ;//kDebug() << "pkcs7 mime == S/MIME TYPE: opaque signed data"; + } else { + ;//kDebug() << "pkcs7 mime - type unknown - opaque signed data ?"; + } - bool sigFound = writeOpaqueOrMultipartSignedData( 0, - *signTestNode, - NodeHelper::fromAsString( node ), - true, - 0, - std::vector(), - isEncrypted ); - if ( sigFound ) { - if ( !isSigned ) { - //kDebug() << "pkcs7 mime - signature found - opaque signed data !"; - isSigned = true; - } + bool sigFound = writeOpaqueOrMultipartSignedData( 0, + *signTestNode, + NodeHelper::fromAsString( node ), + true, + 0, + std::vector(), + isEncrypted ); + if ( sigFound ) { + if ( !isSigned ) { + //kDebug() << "pkcs7 mime - signature found - opaque signed data !"; + isSigned = true; + } - mNodeHelper->setSignatureState( signTestNode, KMMsgFullySigned ); - if ( signTestNode != node ) - mNodeHelper->setSignatureState( node, KMMsgFullySigned ); - } else { - //kDebug() << "pkcs7 mime - NO signature found :-("; + mNodeHelper->setSignatureState( signTestNode, KMMsgFullySigned ); + if ( signTestNode != node ) + mNodeHelper->setSignatureState( node, KMMsgFullySigned ); + } else { + //kDebug() << "pkcs7 mime - NO signature found :-("; + } } - } - return isSigned || isEncrypted; + return isSigned || isEncrypted; } bool ObjectTreeParser::decryptChiasmus( const QByteArray& data, QByteArray& bodyDecoded, QString& errorText ) { - const Kleo::CryptoBackend::Protocol * chiasmus = - Kleo::CryptoBackendFactory::instance()->protocol( "Chiasmus" ); - if ( !chiasmus ) - return false; + const Kleo::CryptoBackend::Protocol * chiasmus = + Kleo::CryptoBackendFactory::instance()->protocol( "Chiasmus" ); + if ( !chiasmus ) + return false; - const std::auto_ptr listjob( chiasmus->specialJob( "x-obtain-keys", QMap() ) ); - if ( !listjob.get() ) { - errorText = i18n( "Chiasmus backend does not offer the " - "\"x-obtain-keys\" function. Please report this bug." ); - return false; - } + const std::auto_ptr listjob( chiasmus->specialJob( "x-obtain-keys", QMap() ) ); + if ( !listjob.get() ) { + errorText = i18n( "Chiasmus backend does not offer the " + "\"x-obtain-keys\" function. Please report this bug." ); + return false; + } - if ( listjob->exec() ) { - errorText = i18n( "Chiasmus Backend Error" ); - return false; - } + if ( listjob->exec() ) { + errorText = i18n( "Chiasmus Backend Error" ); + return false; + } - const QVariant result = listjob->property( "result" ); - if ( result.type() != QVariant::StringList ) { - errorText = i18n( "Unexpected return value from Chiasmus backend: " - "The \"x-obtain-keys\" function did not return a " - "string list. Please report this bug." ); - return false; - } + const QVariant result = listjob->property( "result" ); + if ( result.type() != QVariant::StringList ) { + errorText = i18n( "Unexpected return value from Chiasmus backend: " + "The \"x-obtain-keys\" function did not return a " + "string list. Please report this bug." ); + return false; + } - const QStringList keys = result.toStringList(); - if ( keys.empty() ) { - errorText = i18n( "No keys have been found. Please check that a " - "valid key path has been set in the Chiasmus " - "configuration." ); - return false; - } + const QStringList keys = result.toStringList(); + if ( keys.empty() ) { + errorText = i18n( "No keys have been found. Please check that a " + "valid key path has been set in the Chiasmus " + "configuration." ); + return false; + } - AutoQPointer selectorDlg( new ChiasmusKeySelector( /*mReader*/0, i18n( "Chiasmus Decryption Key Selection" ), - keys, GlobalSettings::chiasmusDecryptionKey(), - GlobalSettings::chiasmusDecryptionOptions() ) ); + AutoQPointer selectorDlg( new ChiasmusKeySelector( /*mReader*/0, i18n( "Chiasmus Decryption Key Selection" ), + keys, GlobalSettings::chiasmusDecryptionKey(), + GlobalSettings::chiasmusDecryptionOptions() ) ); - if ( selectorDlg->exec() != KDialog::Accepted || !selectorDlg ) { - return false; - } - GlobalSettings::setChiasmusDecryptionOptions( selectorDlg->options() ); - GlobalSettings::setChiasmusDecryptionKey( selectorDlg->key() ); - assert( !GlobalSettings::chiasmusDecryptionKey().isEmpty() ); - - Kleo::SpecialJob * job = chiasmus->specialJob( "x-decrypt", QMap() ); - if ( !job ) { - errorText = i18n( "Chiasmus backend does not offer the " - "\"x-decrypt\" function. Please report this bug." ); - return false; - } + if ( selectorDlg->exec() != KDialog::Accepted || !selectorDlg ) { + return false; + } + GlobalSettings::setChiasmusDecryptionOptions( selectorDlg->options() ); + GlobalSettings::setChiasmusDecryptionKey( selectorDlg->key() ); + assert( !GlobalSettings::chiasmusDecryptionKey().isEmpty() ); - if ( !job->setProperty( "key", GlobalSettings::chiasmusDecryptionKey() ) || - !job->setProperty( "options", GlobalSettings::chiasmusDecryptionOptions() ) || - !job->setProperty( "input", data ) ) { - errorText = i18n( "The \"x-decrypt\" function does not accept " - "the expected parameters. Please report this bug." ); - return false; - } + Kleo::SpecialJob * job = chiasmus->specialJob( "x-decrypt", QMap() ); + if ( !job ) { + errorText = i18n( "Chiasmus backend does not offer the " + "\"x-decrypt\" function. Please report this bug." ); + return false; + } - if ( job->exec() ) { - errorText = i18n( "Chiasmus Decryption Error" ); - return false; - } + if ( !job->setProperty( "key", GlobalSettings::chiasmusDecryptionKey() ) || + !job->setProperty( "options", GlobalSettings::chiasmusDecryptionOptions() ) || + !job->setProperty( "input", data ) ) { + errorText = i18n( "The \"x-decrypt\" function does not accept " + "the expected parameters. Please report this bug." ); + return false; + } - const QVariant resultData = job->property( "result" ); - if ( resultData.type() != QVariant::ByteArray ) { - errorText = i18n( "Unexpected return value from Chiasmus backend: " - "The \"x-decrypt\" function did not return a " - "byte array. Please report this bug." ); - return false; - } - bodyDecoded = resultData.toByteArray(); - return true; - } + if ( job->exec() ) { + errorText = i18n( "Chiasmus Decryption Error" ); + return false; + } + + const QVariant resultData = job->property( "result" ); + if ( resultData.type() != QVariant::ByteArray ) { + errorText = i18n( "Unexpected return value from Chiasmus backend: " + "The \"x-decrypt\" function did not return a " + "byte array. Please report this bug." ); + return false; + } + bodyDecoded = resultData.toByteArray(); + return true; +} + +bool ObjectTreeParser::processApplicationChiasmusTextSubtype( KMime::Content * curNode, ProcessResult & result ) +{ + if ( !htmlWriter() ) { + mRawDecryptedBody = curNode->decodedContent(); - bool ObjectTreeParser::processApplicationChiasmusTextSubtype( KMime::Content * curNode, ProcessResult & result ) - { - if ( !htmlWriter() ) { - mRawDecryptedBody = curNode->decodedContent(); + // ### Surely this is totally wrong? The decoded text of this node is just garbage, since it is + // encrypted. This whole if statement should be removed, and the decrypted body + // should be added to mPlainTextContent. Needs testing with Chiasmus though, which I don't have. + mPlainTextContent += curNode->decodedText(); + mPlainTextContentCharset = NodeHelper::charset( curNode ); + return true; + } - // ### Surely this is totally wrong? The decoded text of this node is just garbage, since it is - // encrypted. This whole if statement should be removed, and the decrypted body - // should be added to mPlainTextContent. Needs testing with Chiasmus though, which I don't have. - mPlainTextContent += curNode->decodedText(); - mPlainTextContentCharset = NodeHelper::charset( curNode ); + QByteArray decryptedBody; + QString errorText; + const QByteArray data = curNode->decodedContent(); + bool bOkDecrypt = decryptChiasmus( data, decryptedBody, errorText ); + PartMetaData messagePart; + messagePart.isDecryptable = bOkDecrypt; + messagePart.isEncrypted = true; + messagePart.isSigned = false; + messagePart.errorText = errorText; + if ( htmlWriter() ) + htmlWriter()->queue( writeSigstatHeader( messagePart, + 0, //cryptPlugWrapper(), + NodeHelper::fromAsString( curNode ) ) ); + const QByteArray body = bOkDecrypt ? decryptedBody : data; + const QString chiasmusCharset = curNode->contentType()->parameter(QLatin1String("chiasmus-charset")); + const QTextCodec* aCodec = chiasmusCharset.isEmpty() ? codecFor( curNode ) + : NodeHelper::codecForName( chiasmusCharset.toLatin1() ); + htmlWriter()->queue( quotedHTML( aCodec->toUnicode( body ), false /*decorate*/ ) ); + result.setInlineEncryptionState( KMMsgFullyEncrypted ); + if ( htmlWriter() ) + htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + mNodeHelper->setPartMetaData( curNode, messagePart ); return true; - } - - QByteArray decryptedBody; - QString errorText; - const QByteArray data = curNode->decodedContent(); - bool bOkDecrypt = decryptChiasmus( data, decryptedBody, errorText ); - PartMetaData messagePart; - messagePart.isDecryptable = bOkDecrypt; - messagePart.isEncrypted = true; - messagePart.isSigned = false; - messagePart.errorText = errorText; - if ( htmlWriter() ) - htmlWriter()->queue( writeSigstatHeader( messagePart, - 0, //cryptPlugWrapper(), - NodeHelper::fromAsString( curNode ) ) ); - const QByteArray body = bOkDecrypt ? decryptedBody : data; - const QString chiasmusCharset = curNode->contentType()->parameter(QLatin1String("chiasmus-charset")); - const QTextCodec* aCodec = chiasmusCharset.isEmpty() ? codecFor( curNode ) - : NodeHelper::codecForName( chiasmusCharset.toLatin1() ); - htmlWriter()->queue( quotedHTML( aCodec->toUnicode( body ), false /*decorate*/ ) ); - result.setInlineEncryptionState( KMMsgFullyEncrypted ); - if ( htmlWriter() ) - htmlWriter()->queue( writeSigstatFooter( messagePart ) ); - mNodeHelper->setPartMetaData( curNode, messagePart ); - return true; } void ObjectTreeParser::writeBodyString( const QByteArray & bodyString, @@ -2176,54 +2176,54 @@ ProcessResult & result, bool decorate ) { - assert( codec ); - KMMsgSignatureState inlineSignatureState = result.inlineSignatureState(); - KMMsgEncryptionState inlineEncryptionState = result.inlineEncryptionState(); - writeBodyStr( bodyString, codec, fromAddress, - inlineSignatureState, inlineEncryptionState, decorate ); - result.setInlineSignatureState( inlineSignatureState ); - result.setInlineEncryptionState( inlineEncryptionState ); + assert( codec ); + KMMsgSignatureState inlineSignatureState = result.inlineSignatureState(); + KMMsgEncryptionState inlineEncryptionState = result.inlineEncryptionState(); + writeBodyStr( bodyString, codec, fromAddress, + inlineSignatureState, inlineEncryptionState, decorate ); + result.setInlineSignatureState( inlineSignatureState ); + result.setInlineEncryptionState( inlineEncryptionState ); } void ObjectTreeParser::writePartIcon( KMime::Content * msgPart, bool inlineImage ) { - if ( !htmlWriter() || !msgPart ) - return; + if ( !htmlWriter() || !msgPart ) + return; - const QString name = msgPart->contentType()->name(); - QString label = name.isEmpty() ? NodeHelper::fileName( msgPart ) : name; - if ( label.isEmpty() ) - label = i18nc( "display name for an unnamed attachment", "Unnamed" ); - label = StringUtil::quoteHtmlChars( label, true ); - - QString comment = msgPart->contentDescription()->asUnicodeString(); - comment = StringUtil::quoteHtmlChars( comment, true ); - if ( label == comment ) - comment.clear(); - - QString href = mNodeHelper->asHREF( msgPart, QLatin1String("body") ); - - if ( inlineImage ) { - const QString fileName = mNodeHelper->writeNodeToTempFile( msgPart ); - // show the filename of the image below the embedded image - htmlWriter()->queue( QLatin1String("
" - "" - "
" - "" - "
") + comment + QLatin1String("

") ); - } else { - // show the filename next to the image - const QString iconName = mNodeHelper->iconName( msgPart ); - if( iconName.right( 14 ) == QLatin1String( "mime_empty.png" ) ) { - mNodeHelper->magicSetType( msgPart ); - //iconName = mNodeHelper->iconName( msgPart ); - } - htmlWriter()->queue( QLatin1String("" - "
") + comment +QLatin1String( "

") ); - } + const QString name = msgPart->contentType()->name(); + QString label = name.isEmpty() ? NodeHelper::fileName( msgPart ) : name; + if ( label.isEmpty() ) + label = i18nc( "display name for an unnamed attachment", "Unnamed" ); + label = StringUtil::quoteHtmlChars( label, true ); + + QString comment = msgPart->contentDescription()->asUnicodeString(); + comment = StringUtil::quoteHtmlChars( comment, true ); + if ( label == comment ) + comment.clear(); + + QString href = mNodeHelper->asHREF( msgPart, QLatin1String("body") ); + + if ( inlineImage ) { + const QString fileName = mNodeHelper->writeNodeToTempFile( msgPart ); + // show the filename of the image below the embedded image + htmlWriter()->queue( QLatin1String("
" + "" + "
" + "" + "
") + comment + QLatin1String("

") ); + } else { + // show the filename next to the image + const QString iconName = mNodeHelper->iconName( msgPart ); + if( iconName.right( 14 ) == QLatin1String( "mime_empty.png" ) ) { + mNodeHelper->magicSetType( msgPart ); + //iconName = mNodeHelper->iconName( msgPart ); + } + htmlWriter()->queue( QLatin1String("" + "
") + comment +QLatin1String( "

") ); + } } static const int SIG_FRAME_COL_UNDEF = 99; @@ -2231,43 +2231,43 @@ #define SIG_FRAME_COL_YELLOW 0 #define SIG_FRAME_COL_GREEN 1 QString ObjectTreeParser::sigStatusToString( const Kleo::CryptoBackend::Protocol* cryptProto, - int status_code, - GpgME::Signature::Summary summary, - int& frameColor, - bool& showKeyInfos ) -{ - // note: At the moment frameColor and showKeyInfos are - // used for CMS only but not for PGP signatures - // pending(khz): Implement usage of these for PGP sigs as well. - showKeyInfos = true; - QString result; - if( cryptProto ) { - if( cryptProto == Kleo::CryptoBackendFactory::instance()->openpgp() ) { - // process enum according to it's definition to be read in - // GNU Privacy Guard CVS repository /gpgme/gpgme/gpgme.h - switch( status_code ) { - case 0: // GPGME_SIG_STAT_NONE - result = i18n("Error: Signature not verified"); - break; - case 1: // GPGME_SIG_STAT_GOOD - result = i18n("Good signature"); - break; - case 2: // GPGME_SIG_STAT_BAD - result = i18n("Bad signature"); - break; - case 3: // GPGME_SIG_STAT_NOKEY - result = i18n("No public key to verify the signature"); - break; - case 4: // GPGME_SIG_STAT_NOSIG - result = i18n("No signature found"); - break; - case 5: // GPGME_SIG_STAT_ERROR - result = i18n("Error verifying the signature"); - break; - case 6: // GPGME_SIG_STAT_DIFF - result = i18n("Different results for signatures"); - break; - /* PENDING(khz) Verify exact meaning of the following values: + int status_code, + GpgME::Signature::Summary summary, + int& frameColor, + bool& showKeyInfos ) +{ + // note: At the moment frameColor and showKeyInfos are + // used for CMS only but not for PGP signatures + // pending(khz): Implement usage of these for PGP sigs as well. + showKeyInfos = true; + QString result; + if( cryptProto ) { + if( cryptProto == Kleo::CryptoBackendFactory::instance()->openpgp() ) { + // process enum according to it's definition to be read in + // GNU Privacy Guard CVS repository /gpgme/gpgme/gpgme.h + switch( status_code ) { + case 0: // GPGME_SIG_STAT_NONE + result = i18n("Error: Signature not verified"); + break; + case 1: // GPGME_SIG_STAT_GOOD + result = i18n("Good signature"); + break; + case 2: // GPGME_SIG_STAT_BAD + result = i18n("Bad signature"); + break; + case 3: // GPGME_SIG_STAT_NOKEY + result = i18n("No public key to verify the signature"); + break; + case 4: // GPGME_SIG_STAT_NOSIG + result = i18n("No signature found"); + break; + case 5: // GPGME_SIG_STAT_ERROR + result = i18n("Error verifying the signature"); + break; + case 6: // GPGME_SIG_STAT_DIFF + result = i18n("Different results for signatures"); + break; + /* PENDING(khz) Verify exact meaning of the following values: case 7: // GPGME_SIG_STAT_GOOD_EXP return i18n("Signature certificate is expired"); break; @@ -2275,635 +2275,635 @@ return i18n("One of the certificate's keys is expired"); break; */ - default: - result.clear(); // do *not* return a default text here ! - break; - } - } - else if ( cryptProto == Kleo::CryptoBackendFactory::instance()->smime() ) { - // process status bits according to SigStatus_... - // definitions in kdenetwork/libkdenetwork/cryptplug.h - - if( summary == GpgME::Signature::None ) { - result = i18n("No status information available."); - frameColor = SIG_FRAME_COL_YELLOW; - showKeyInfos = false; - return result; - } - - if( summary & GpgME::Signature::Valid ) { - result = i18n("Good signature."); - // Note: - // Here we are work differently than KMail did before! - // - // The GOOD case ( == sig matching and the complete - // certificate chain was verified and is valid today ) - // by definition does *not* show any key - // information but just states that things are OK. - // (khz, according to LinuxTag 2002 meeting) - frameColor = SIG_FRAME_COL_GREEN; - showKeyInfos = false; - return result; - } - - // we are still there? OK, let's test the different cases: - - // we assume green, test for yellow or red (in this order!) - frameColor = SIG_FRAME_COL_GREEN; - QString result2; - if( summary & GpgME::Signature::KeyExpired ){ - // still is green! - result2 += i18n("One key has expired."); - } - if( summary & GpgME::Signature::SigExpired ){ - // and still is green! - result2 += i18n("The signature has expired."); - } - - // test for yellow: - if( summary & GpgME::Signature::KeyMissing ) { - result2 += i18n("Unable to verify: key missing."); - // if the signature certificate is missing - // we cannot show information on it - showKeyInfos = false; - frameColor = SIG_FRAME_COL_YELLOW; - } - if( summary & GpgME::Signature::CrlMissing ){ - result2 += i18n("CRL not available."); - frameColor = SIG_FRAME_COL_YELLOW; - } - if( summary & GpgME::Signature::CrlTooOld ){ - result2 += i18n("Available CRL is too old."); - frameColor = SIG_FRAME_COL_YELLOW; - } - if( summary & GpgME::Signature::BadPolicy ){ - result2 += i18n("A policy was not met."); - frameColor = SIG_FRAME_COL_YELLOW; - } - if( summary & GpgME::Signature::SysError ){ - result2 += i18n("A system error occurred."); - // if a system error occurred - // we cannot trust any information - // that was given back by the plug-in - showKeyInfos = false; - frameColor = SIG_FRAME_COL_YELLOW; - } - - // test for red: - if( summary & GpgME::Signature::KeyRevoked ){ - // this is red! - result2 += i18n("One key has been revoked."); - frameColor = SIG_FRAME_COL_RED; - } - if( summary & GpgME::Signature::Red ) { - if( result2.isEmpty() ) - // Note: - // Here we are work differently than KMail did before! - // - // The BAD case ( == sig *not* matching ) - // by definition does *not* show any key - // information but just states that things are BAD. - // - // The reason for this: In this case ALL information - // might be falsificated, we can NOT trust the data - // in the body NOT the signature - so we don't show - // any key/signature information at all! - // (khz, according to LinuxTag 2002 meeting) - showKeyInfos = false; - frameColor = SIG_FRAME_COL_RED; - } - else - result.clear(); - - if( SIG_FRAME_COL_GREEN == frameColor ) { - result = i18n("Good signature."); - } else if( SIG_FRAME_COL_RED == frameColor ) { - result = i18n("Bad signature."); - } else - result.clear(); - - if( !result2.isEmpty() ) { - if( !result.isEmpty() ) - result.append(QLatin1String("
")); - result.append( result2 ); - } - } - /* + default: + result.clear(); // do *not* return a default text here ! + break; + } + } + else if ( cryptProto == Kleo::CryptoBackendFactory::instance()->smime() ) { + // process status bits according to SigStatus_... + // definitions in kdenetwork/libkdenetwork/cryptplug.h + + if( summary == GpgME::Signature::None ) { + result = i18n("No status information available."); + frameColor = SIG_FRAME_COL_YELLOW; + showKeyInfos = false; + return result; + } + + if( summary & GpgME::Signature::Valid ) { + result = i18n("Good signature."); + // Note: + // Here we are work differently than KMail did before! + // + // The GOOD case ( == sig matching and the complete + // certificate chain was verified and is valid today ) + // by definition does *not* show any key + // information but just states that things are OK. + // (khz, according to LinuxTag 2002 meeting) + frameColor = SIG_FRAME_COL_GREEN; + showKeyInfos = false; + return result; + } + + // we are still there? OK, let's test the different cases: + + // we assume green, test for yellow or red (in this order!) + frameColor = SIG_FRAME_COL_GREEN; + QString result2; + if( summary & GpgME::Signature::KeyExpired ){ + // still is green! + result2 += i18n("One key has expired."); + } + if( summary & GpgME::Signature::SigExpired ){ + // and still is green! + result2 += i18n("The signature has expired."); + } + + // test for yellow: + if( summary & GpgME::Signature::KeyMissing ) { + result2 += i18n("Unable to verify: key missing."); + // if the signature certificate is missing + // we cannot show information on it + showKeyInfos = false; + frameColor = SIG_FRAME_COL_YELLOW; + } + if( summary & GpgME::Signature::CrlMissing ){ + result2 += i18n("CRL not available."); + frameColor = SIG_FRAME_COL_YELLOW; + } + if( summary & GpgME::Signature::CrlTooOld ){ + result2 += i18n("Available CRL is too old."); + frameColor = SIG_FRAME_COL_YELLOW; + } + if( summary & GpgME::Signature::BadPolicy ){ + result2 += i18n("A policy was not met."); + frameColor = SIG_FRAME_COL_YELLOW; + } + if( summary & GpgME::Signature::SysError ){ + result2 += i18n("A system error occurred."); + // if a system error occurred + // we cannot trust any information + // that was given back by the plug-in + showKeyInfos = false; + frameColor = SIG_FRAME_COL_YELLOW; + } + + // test for red: + if( summary & GpgME::Signature::KeyRevoked ){ + // this is red! + result2 += i18n("One key has been revoked."); + frameColor = SIG_FRAME_COL_RED; + } + if( summary & GpgME::Signature::Red ) { + if( result2.isEmpty() ) + // Note: + // Here we are work differently than KMail did before! + // + // The BAD case ( == sig *not* matching ) + // by definition does *not* show any key + // information but just states that things are BAD. + // + // The reason for this: In this case ALL information + // might be falsificated, we can NOT trust the data + // in the body NOT the signature - so we don't show + // any key/signature information at all! + // (khz, according to LinuxTag 2002 meeting) + showKeyInfos = false; + frameColor = SIG_FRAME_COL_RED; + } + else + result.clear(); + + if( SIG_FRAME_COL_GREEN == frameColor ) { + result = i18n("Good signature."); + } else if( SIG_FRAME_COL_RED == frameColor ) { + result = i18n("Bad signature."); + } else + result.clear(); + + if( !result2.isEmpty() ) { + if( !result.isEmpty() ) + result.append(QLatin1String("
")); + result.append( result2 ); + } + } + /* // add i18n support for 3rd party plug-ins here: else if ( cryptPlug->libName().contains( "yetanotherpluginname", Qt::CaseInsensitive )) { } */ - } - return result; + } + return result; } static QString writeSimpleSigstatHeader( const PartMetaData &block ) { - QString html; - html += QLatin1String("
"); + QString html; + html += QLatin1String("
"); + + if ( block.signClass == QLatin1String( "signErr" ) ) { + html += i18n( "Invalid signature." ); + } else if ( block.signClass == QLatin1String( "signOkKeyBad" ) + || block.signClass == QLatin1String( "signWarn" ) ) { + html += i18n( "Not enough information to check signature validity." ); + } else if ( block.signClass == QLatin1String( "signOkKeyOk" ) ) { + + QString addr; + if ( !block.signerMailAddresses.isEmpty() ) + addr = block.signerMailAddresses.first(); + + QString name = addr; + if ( name.isEmpty() ) + name = block.signer; + + if ( addr.isEmpty() ) { + html += i18n( "Signature is valid." ); + } else { + html += i18n( "Signed by %2.", addr, name ); + } - if ( block.signClass == QLatin1String( "signErr" ) ) { - html += i18n( "Invalid signature." ); - } else if ( block.signClass == QLatin1String( "signOkKeyBad" ) - || block.signClass == QLatin1String( "signWarn" ) ) { - html += i18n( "Not enough information to check signature validity." ); - } else if ( block.signClass == QLatin1String( "signOkKeyOk" ) ) { - - QString addr; - if ( !block.signerMailAddresses.isEmpty() ) - addr = block.signerMailAddresses.first(); - - QString name = addr; - if ( name.isEmpty() ) - name = block.signer; - - if ( addr.isEmpty() ) { - html += i18n( "Signature is valid." ); } else { - html += i18n( "Signed by %2.", addr, name ); + // should not happen + html += i18n( "Unknown signature state" ); } - - } else { - // should not happen - html += i18n( "Unknown signature state" ); - } - html += QLatin1String(""); - html += QLatin1String(""); - html += i18n( "Show Details" ); - html += QLatin1String("
"); - return html; + html += QLatin1String("
"); + html += QLatin1String(""); + html += i18n( "Show Details" ); + html += QLatin1String("
"); + return html; } static QString beginVerboseSigstatHeader() { - return QLatin1String(""); + html += QLatin1String("
"); + return QLatin1String(""); - html += QLatin1String("
"); } static QString makeShowAuditLogLink( const GpgME::Error & err, const QString & auditLog ) { - // more or less the same as - // kleopatra/utils/auditlog.cpp:formatLink(), so any bug fixed here - // equally applies there: - if ( const unsigned int code = err.code() ) { - if ( code == GPG_ERR_NOT_IMPLEMENTED ) { - kDebug() << "not showing link (not implemented)"; - return QString(); - } else if ( code == GPG_ERR_NO_DATA ) { - kDebug() << "not showing link (not available)"; - return i18n("No Audit Log available"); - } else { - return i18n("Error Retrieving Audit Log: %1", QString::fromLocal8Bit( err.asString() ) ); + // more or less the same as + // kleopatra/utils/auditlog.cpp:formatLink(), so any bug fixed here + // equally applies there: + if ( const unsigned int code = err.code() ) { + if ( code == GPG_ERR_NOT_IMPLEMENTED ) { + kDebug() << "not showing link (not implemented)"; + return QString(); + } else if ( code == GPG_ERR_NO_DATA ) { + kDebug() << "not showing link (not available)"; + return i18n("No Audit Log available"); + } else { + return i18n("Error Retrieving Audit Log: %1", QString::fromLocal8Bit( err.asString() ) ); + } } - } - if ( !auditLog.isEmpty() ) { - KUrl url; - url.setScheme( QLatin1String("kmail") ); - url.setPath( QLatin1String("showAuditLog") ); - url.addQueryItem( QLatin1String("log"), auditLog ); + if ( !auditLog.isEmpty() ) { + KUrl url; + url.setScheme( QLatin1String("kmail") ); + url.setPath( QLatin1String("showAuditLog") ); + url.addQueryItem( QLatin1String("log"), auditLog ); - return QLatin1String("") + i18nc("The Audit Log is a detailed error log from the gnupg backend", "Show Audit Log") + QLatin1String(""); - } + return QLatin1String("") + i18nc("The Audit Log is a detailed error log from the gnupg backend", "Show Audit Log") + QLatin1String(""); + } - return QString(); + return QString(); } static QString endVerboseSigstatHeader( const PartMetaData & pmd ) { - QString html; - html += QLatin1String(""); - html += QLatin1String(""); - html += i18n( "Hide Details" ); - html += QLatin1String("
"); - html += makeShowAuditLogLink( pmd.auditLogError, pmd.auditLog ); - html += QLatin1String("
"); - return html; + QString html; + html += QLatin1String("
"); + html += QLatin1String(""); + html += i18n( "Hide Details" ); + html += QLatin1String("
"); + html += makeShowAuditLogLink( pmd.auditLogError, pmd.auditLog ); + html += QLatin1String("
"); + return html; } QString ObjectTreeParser::writeSigstatHeader( PartMetaData & block, - const Kleo::CryptoBackend::Protocol * cryptProto, - const QString & fromAddress, - KMime::Content *node ) -{ - const bool isSMIME = cryptProto && ( cryptProto == Kleo::CryptoBackendFactory::instance()->smime() ); - QString signer = block.signer; - - QString htmlStr, simpleHtmlStr; - const QString dir = QApplication::isRightToLeft() ? QLatin1String("rtl") : QLatin1String("ltr"); - QString cellPadding(QLatin1String("cellpadding=\"1\"")); - - if( block.isEncapsulatedRfc822Message ) - { - htmlStr += QLatin1String("" - "
"); - if( node ) { - htmlStr += QLatin1String("asHREF( node, QLatin1String("body") ) + QLatin1String("\">") + const Kleo::CryptoBackend::Protocol * cryptProto, + const QString & fromAddress, + KMime::Content *node ) +{ + const bool isSMIME = cryptProto && ( cryptProto == Kleo::CryptoBackendFactory::instance()->smime() ); + QString signer = block.signer; + + QString htmlStr, simpleHtmlStr; + const QString dir = QApplication::isRightToLeft() ? QLatin1String("rtl") : QLatin1String("ltr"); + QString cellPadding(QLatin1String("cellpadding=\"1\"")); + + if( block.isEncapsulatedRfc822Message ) + { + htmlStr += QLatin1String("" + "
"); + if( node ) { + htmlStr += QLatin1String("asHREF( node, QLatin1String("body") ) + QLatin1String("\">") + i18n("Encapsulated message") + QLatin1String(""); - } else { - htmlStr += i18n("Encapsulated message"); - } - htmlStr += QLatin1String("
"); - } + } else { + htmlStr += i18n("Encapsulated message"); + } + htmlStr += QLatin1String("
"); + } - if( block.isEncrypted ) { - htmlStr += QLatin1String("" - "
"); - if ( block.inProgress ) { - htmlStr += i18n("Please wait while the message is being decrypted..."); - } else if( block.isDecryptable ) { - htmlStr += i18n("Encrypted message"); - } else { - htmlStr += i18n("Encrypted message (decryption not possible)"); - if( !block.errorText.isEmpty() ) { - htmlStr += QLatin1String("
") + i18n("Reason: %1", block.errorText ); - } - } - htmlStr += QLatin1String("
"); - } + if( block.isEncrypted ) { + htmlStr += QLatin1String("" + "
"); + if ( block.inProgress ) { + htmlStr += i18n("Please wait while the message is being decrypted..."); + } else if( block.isDecryptable ) { + htmlStr += i18n("Encrypted message"); + } else { + htmlStr += i18n("Encrypted message (decryption not possible)"); + if( !block.errorText.isEmpty() ) { + htmlStr += QLatin1String("
") + i18n("Reason: %1", block.errorText ); + } + } + htmlStr += QLatin1String("
"); + } - if ( block.isSigned && block.inProgress ) { - block.signClass =QLatin1String( "signInProgress"); - htmlStr += QLatin1String("" - "
"); - htmlStr += i18n("Please wait while the signature is being verified..."); - htmlStr += QLatin1String("
"); - } + if ( block.isSigned && block.inProgress ) { + block.signClass =QLatin1String( "signInProgress"); + htmlStr += QLatin1String("" + "
"); + htmlStr += i18n("Please wait while the signature is being verified..."); + htmlStr += QLatin1String("
"); + } + + simpleHtmlStr = htmlStr; + + if( block.isSigned && !block.inProgress ) { + QStringList& blockAddrs( block.signerMailAddresses ); + // note: At the moment frameColor and showKeyInfos are + // used for CMS only but not for PGP signatures + // pending(khz): Implement usage of these for PGP sigs as well. + int frameColor = SIG_FRAME_COL_UNDEF; + bool showKeyInfos; + bool onlyShowKeyURL = false; + bool cannotCheckSignature = true; + QString statusStr = sigStatusToString( cryptProto, + block.status_code, + block.sigSummary, + frameColor, + showKeyInfos ); + // if needed fallback to english status text + // that was reported by the plugin + if( statusStr.isEmpty() ) + statusStr = block.status; + if( block.technicalProblem ) + frameColor = SIG_FRAME_COL_YELLOW; + + switch( frameColor ){ + case SIG_FRAME_COL_RED: + cannotCheckSignature = false; + break; + case SIG_FRAME_COL_YELLOW: + cannotCheckSignature = true; + break; + case SIG_FRAME_COL_GREEN: + cannotCheckSignature = false; + break; + } - simpleHtmlStr = htmlStr; + // compose the string for displaying the key ID + // either as URL or not linked (for unknown crypto) + // note: Once we can start PGP key manager programs + // from within KMail we could change this and + // always show the URL. (khz, 2002/06/27) + QString startKeyHREF; + QString keyWithWithoutURL; + if ( cryptProto ) { + startKeyHREF = + QString::fromLatin1("") + .arg( cryptProto->displayName(), + cryptProto->name(), + QString::fromLatin1( block.keyId ) ); - if( block.isSigned && !block.inProgress ) { - QStringList& blockAddrs( block.signerMailAddresses ); - // note: At the moment frameColor and showKeyInfos are - // used for CMS only but not for PGP signatures - // pending(khz): Implement usage of these for PGP sigs as well. - int frameColor = SIG_FRAME_COL_UNDEF; - bool showKeyInfos; - bool onlyShowKeyURL = false; - bool cannotCheckSignature = true; - QString statusStr = sigStatusToString( cryptProto, - block.status_code, - block.sigSummary, - frameColor, - showKeyInfos ); - // if needed fallback to english status text - // that was reported by the plugin - if( statusStr.isEmpty() ) - statusStr = block.status; - if( block.technicalProblem ) - frameColor = SIG_FRAME_COL_YELLOW; - - switch( frameColor ){ - case SIG_FRAME_COL_RED: - cannotCheckSignature = false; - break; - case SIG_FRAME_COL_YELLOW: - cannotCheckSignature = true; - break; - case SIG_FRAME_COL_GREEN: - cannotCheckSignature = false; - break; - } + keyWithWithoutURL = + QString::fromLatin1("%1%2").arg( startKeyHREF, QString::fromLatin1(QByteArray(QByteArray("0x") + block.keyId)) ); + } else { + keyWithWithoutURL = QLatin1String("0x") + QString::fromUtf8( block.keyId ); + } - // compose the string for displaying the key ID - // either as URL or not linked (for unknown crypto) - // note: Once we can start PGP key manager programs - // from within KMail we could change this and - // always show the URL. (khz, 2002/06/27) - QString startKeyHREF; - QString keyWithWithoutURL; - if ( cryptProto ) { - startKeyHREF = - QString::fromLatin1("") - .arg( cryptProto->displayName(), - cryptProto->name(), - QString::fromLatin1( block.keyId ) ); - - keyWithWithoutURL = - QString::fromLatin1("%1%2").arg( startKeyHREF, QString::fromLatin1(QByteArray(QByteArray("0x") + block.keyId)) ); - } else { - keyWithWithoutURL = QLatin1String("0x") + QString::fromUtf8( block.keyId ); - } + // temporary hack: always show key information! + showKeyInfos = true; - // temporary hack: always show key information! - showKeyInfos = true; + // Sorry for using 'black' as null color but .isValid() + // checking with QColor default c'tor did not work for + // some reason. + if( isSMIME && (SIG_FRAME_COL_UNDEF != frameColor) ) { + + // new frame settings for CMS: + // beautify the status string + if( !statusStr.isEmpty() ) { + statusStr.prepend(QLatin1String("")); + statusStr.append( QLatin1String("")); + } - // Sorry for using 'black' as null color but .isValid() - // checking with QColor default c'tor did not work for - // some reason. - if( isSMIME && (SIG_FRAME_COL_UNDEF != frameColor) ) { - - // new frame settings for CMS: - // beautify the status string - if( !statusStr.isEmpty() ) { - statusStr.prepend(QLatin1String("")); - statusStr.append( QLatin1String("")); - } - - // special color handling: S/MIME uses only green/yellow/red. - switch( frameColor ) { - case SIG_FRAME_COL_RED: - block.signClass = QLatin1String("signErr");//"signCMSRed"; - onlyShowKeyURL = true; - break; - case SIG_FRAME_COL_YELLOW: - if( block.technicalProblem ) - block.signClass = QLatin1String("signWarn"); - else - block.signClass = QLatin1String("signOkKeyBad");//"signCMSYellow"; - break; - case SIG_FRAME_COL_GREEN: - block.signClass = QLatin1String("signOkKeyOk");//"signCMSGreen"; - // extra hint for green case - // that email addresses in DN do not match fromAddress - QString greenCaseWarning; - QString msgFrom( KPIMUtils::extractEmailAddress(fromAddress) ); - QString certificate; - if( block.keyId.isEmpty() ) - certificate = i18n("certificate"); - else - certificate = startKeyHREF + i18n("certificate") + QLatin1String(""); - if( !blockAddrs.empty() ){ - if( !blockAddrs.contains( msgFrom, Qt::CaseInsensitive ) ) { - greenCaseWarning = - QLatin1String("") + - i18nc("Start of warning message." - ,"Warning:") + - QLatin1String(" ") + - i18n("Sender's mail address is not stored " - "in the %1 used for signing.", certificate) + - QLatin1String("
") + - i18n("sender: ") + - msgFrom + - QLatin1String("
") + - i18n("stored: "); - // We cannot use Qt's join() function here but - // have to join the addresses manually to - // extract the mail addresses (without '<''>') - // before including it into our string: - bool bStart = true; - for(QStringList::ConstIterator it = blockAddrs.constBegin(); - it != blockAddrs.constEnd(); ++it ){ - if( !bStart ) - greenCaseWarning.append(QLatin1String(",
   ")); - bStart = false; - greenCaseWarning.append( KPIMUtils::extractEmailAddress(*it) ); - } - } - } else { - greenCaseWarning = - QLatin1String("") + - i18nc("Start of warning message.","Warning:") + - QLatin1String(" ") + - i18n("No mail address is stored in the %1 used for signing, " - "so we cannot compare it to the sender's address %2.", - certificate, - msgFrom); - } - if( !greenCaseWarning.isEmpty() ) { - if( !statusStr.isEmpty() ) - statusStr.append(QLatin1String("
 
")); - statusStr.append( greenCaseWarning ); - } - break; - } - - QString frame = QLatin1String("" - "
"); - htmlStr += frame + beginVerboseSigstatHeader(); - simpleHtmlStr += frame; - simpleHtmlStr += writeSimpleSigstatHeader( block ); - if( block.technicalProblem ) { - htmlStr += block.errorText; - } - else if( showKeyInfos ) { - if( cannotCheckSignature ) { - htmlStr += i18n( "Not enough information to check " - "signature. %1", - keyWithWithoutURL ); - } - else { - - if (block.signer.isEmpty()) - signer.clear(); - else { - if( !blockAddrs.empty() ){ - const KUrl address = KPIMUtils::encodeMailtoUrl( blockAddrs.first() ); - signer = QLatin1String("") + signer + QLatin1String(""); - } - } - - if( block.keyId.isEmpty() ) { - if( signer.isEmpty() || onlyShowKeyURL ) - htmlStr += i18n( "Message was signed with unknown key." ); - else - htmlStr += i18n( "Message was signed by %1.", - signer ); - } else { - QDateTime created = block.creationTime; - if( created.isValid() ) { - if( signer.isEmpty() ) { - if( onlyShowKeyURL ) - htmlStr += i18n( "Message was signed with key %1.", - keyWithWithoutURL ); - else - htmlStr += i18n( "Message was signed on %1 with key %2.", - KGlobal::locale()->formatDateTime( created ), - keyWithWithoutURL ); - } - else { - if( onlyShowKeyURL ) - htmlStr += i18n( "Message was signed with key %1.", - keyWithWithoutURL ); - else - htmlStr += i18n( "Message was signed by %3 on %1 with key %2", - KGlobal::locale()->formatDateTime( created ), - keyWithWithoutURL, - signer ); - } - } - else { - if( signer.isEmpty() || onlyShowKeyURL ) - htmlStr += i18n( "Message was signed with key %1.", - keyWithWithoutURL ); - else - htmlStr += i18n( "Message was signed by %2 with key %1.", - keyWithWithoutURL, - signer ); - } - } - } - htmlStr += QLatin1String("
"); - if( !statusStr.isEmpty() ) { - htmlStr += QLatin1String(" 
"); - htmlStr += i18n( "Status: " ); - htmlStr += statusStr; - } - } else { - htmlStr += statusStr; - } - frame = QLatin1String("
"); - htmlStr += endVerboseSigstatHeader( block ) + frame; - simpleHtmlStr += frame; - - } else { - - // old frame settings for PGP: - - if( block.signer.isEmpty() || block.technicalProblem ) { - block.signClass = QLatin1String("signWarn"); - QString frame = QLatin1String("" - "
"); - htmlStr += frame + beginVerboseSigstatHeader(); - simpleHtmlStr += frame; - simpleHtmlStr += writeSimpleSigstatHeader( block ); - if( block.technicalProblem ) { - htmlStr += block.errorText; - } - else { - if( !block.keyId.isEmpty() ) { - QDateTime created = block.creationTime; - if ( created.isValid() ) - htmlStr += i18n( "Message was signed on %1 with unknown key %2.", - KGlobal::locale()->formatDateTime( created ), - keyWithWithoutURL ); - else - htmlStr += i18n( "Message was signed with unknown key %1.", - keyWithWithoutURL ); - } + // special color handling: S/MIME uses only green/yellow/red. + switch( frameColor ) { + case SIG_FRAME_COL_RED: + block.signClass = QLatin1String("signErr");//"signCMSRed"; + onlyShowKeyURL = true; + break; + case SIG_FRAME_COL_YELLOW: + if( block.technicalProblem ) + block.signClass = QLatin1String("signWarn"); + else + block.signClass = QLatin1String("signOkKeyBad");//"signCMSYellow"; + break; + case SIG_FRAME_COL_GREEN: + block.signClass = QLatin1String("signOkKeyOk");//"signCMSGreen"; + // extra hint for green case + // that email addresses in DN do not match fromAddress + QString greenCaseWarning; + QString msgFrom( KPIMUtils::extractEmailAddress(fromAddress) ); + QString certificate; + if( block.keyId.isEmpty() ) + certificate = i18n("certificate"); else - htmlStr += i18n( "Message was signed with unknown key." ); + certificate = startKeyHREF + i18n("certificate") + QLatin1String(""); + if( !blockAddrs.empty() ){ + if( !blockAddrs.contains( msgFrom, Qt::CaseInsensitive ) ) { + greenCaseWarning = + QLatin1String("") + + i18nc("Start of warning message." + ,"Warning:") + + QLatin1String(" ") + + i18n("Sender's mail address is not stored " + "in the %1 used for signing.", certificate) + + QLatin1String("
") + + i18n("sender: ") + + msgFrom + + QLatin1String("
") + + i18n("stored: "); + // We cannot use Qt's join() function here but + // have to join the addresses manually to + // extract the mail addresses (without '<''>') + // before including it into our string: + bool bStart = true; + for(QStringList::ConstIterator it = blockAddrs.constBegin(); + it != blockAddrs.constEnd(); ++it ){ + if( !bStart ) + greenCaseWarning.append(QLatin1String(",
   ")); + bStart = false; + greenCaseWarning.append( KPIMUtils::extractEmailAddress(*it) ); + } + } + } else { + greenCaseWarning = + QLatin1String("") + + i18nc("Start of warning message.","Warning:") + + QLatin1String(" ") + + i18n("No mail address is stored in the %1 used for signing, " + "so we cannot compare it to the sender's address %2.", + certificate, + msgFrom); + } + if( !greenCaseWarning.isEmpty() ) { + if( !statusStr.isEmpty() ) + statusStr.append(QLatin1String("
 
")); + statusStr.append( greenCaseWarning ); + } + break; + } + + QString frame = QLatin1String("" + "
"); + htmlStr += frame + beginVerboseSigstatHeader(); + simpleHtmlStr += frame; + simpleHtmlStr += writeSimpleSigstatHeader( block ); + if( block.technicalProblem ) { + htmlStr += block.errorText; + } + else if( showKeyInfos ) { + if( cannotCheckSignature ) { + htmlStr += i18n( "Not enough information to check " + "signature. %1", + keyWithWithoutURL ); + } + else { + + if (block.signer.isEmpty()) + signer.clear(); + else { + if( !blockAddrs.empty() ){ + const KUrl address = KPIMUtils::encodeMailtoUrl( blockAddrs.first() ); + signer = QLatin1String("") + signer + QLatin1String(""); + } + } + + if( block.keyId.isEmpty() ) { + if( signer.isEmpty() || onlyShowKeyURL ) + htmlStr += i18n( "Message was signed with unknown key." ); + else + htmlStr += i18n( "Message was signed by %1.", + signer ); + } else { + QDateTime created = block.creationTime; + if( created.isValid() ) { + if( signer.isEmpty() ) { + if( onlyShowKeyURL ) + htmlStr += i18n( "Message was signed with key %1.", + keyWithWithoutURL ); + else + htmlStr += i18n( "Message was signed on %1 with key %2.", + KGlobal::locale()->formatDateTime( created ), + keyWithWithoutURL ); + } + else { + if( onlyShowKeyURL ) + htmlStr += i18n( "Message was signed with key %1.", + keyWithWithoutURL ); + else + htmlStr += i18n( "Message was signed by %3 on %1 with key %2", + KGlobal::locale()->formatDateTime( created ), + keyWithWithoutURL, + signer ); + } + } + else { + if( signer.isEmpty() || onlyShowKeyURL ) + htmlStr += i18n( "Message was signed with key %1.", + keyWithWithoutURL ); + else + htmlStr += i18n( "Message was signed by %2 with key %1.", + keyWithWithoutURL, + signer ); + } + } + } htmlStr += QLatin1String("
"); - htmlStr += i18n( "The validity of the signature cannot be " - "verified." ); if( !statusStr.isEmpty() ) { - htmlStr += QLatin1String("
"); - htmlStr += i18n( "Status: " ); - htmlStr += QLatin1String(""); - htmlStr += statusStr; - htmlStr += QLatin1String(""); - } - } - frame = QLatin1String("
"); - htmlStr += endVerboseSigstatHeader( block ) + frame; - simpleHtmlStr += frame; - } - else - { - // HTMLize the signer's user id and create mailto: link - signer = StringUtil::quoteHtmlChars( signer, true ); - signer = QLatin1String("") + signer + QLatin1String(""); - - if (block.isGoodSignature) { - if( block.keyTrust < Kpgp::KPGP_VALIDITY_MARGINAL ) - block.signClass = QLatin1String("signOkKeyBad"); - else - block.signClass = QLatin1String("signOkKeyOk"); - QString frame = QLatin1String("" - "" - "
"); - htmlStr += frame + beginVerboseSigstatHeader(); - simpleHtmlStr += frame; - simpleHtmlStr += writeSimpleSigstatHeader( block ); - if( !block.keyId.isEmpty() ) - htmlStr += i18n( "Message was signed by %2 (Key ID: %1).", - keyWithWithoutURL, - signer ); - else - htmlStr += i18n( "Message was signed by %1.", signer ); - htmlStr += QLatin1String("
"); - - switch( block.keyTrust ) - { - case Kpgp::KPGP_VALIDITY_UNKNOWN: - htmlStr += i18n( "The signature is valid, but the key's " - "validity is unknown." ); - break; - case Kpgp::KPGP_VALIDITY_MARGINAL: - htmlStr += i18n( "The signature is valid and the key is " - "marginally trusted." ); - break; - case Kpgp::KPGP_VALIDITY_FULL: - htmlStr += i18n( "The signature is valid and the key is " - "fully trusted." ); - break; - case Kpgp::KPGP_VALIDITY_ULTIMATE: - htmlStr += i18n( "The signature is valid and the key is " - "ultimately trusted." ); - break; - default: - htmlStr += i18n( "The signature is valid, but the key is " - "untrusted." ); - } - frame = QLatin1String("
"); - htmlStr += endVerboseSigstatHeader( block ) + frame; - simpleHtmlStr += frame; - } - else - { - block.signClass = QLatin1String("signErr"); - QString frame = QLatin1String("" - "" - "
"); - htmlStr += frame + beginVerboseSigstatHeader(); - simpleHtmlStr += frame; - simpleHtmlStr += writeSimpleSigstatHeader( block ); - if( !block.keyId.isEmpty() ) - htmlStr += i18n( "Message was signed by %2 (Key ID: %1).", - keyWithWithoutURL, - signer ); - else - htmlStr += i18n( "Message was signed by %1.", signer ); - htmlStr += QLatin1String("
"); - htmlStr += i18n("Warning: The signature is bad."); - frame = QLatin1String("
"); - htmlStr += endVerboseSigstatHeader( block ) + frame; - simpleHtmlStr += frame; - } - } - } - } + htmlStr += QLatin1String(" 
"); + htmlStr += i18n( "Status: " ); + htmlStr += statusStr; + } + } else { + htmlStr += statusStr; + } + frame = QLatin1String("
"); + htmlStr += endVerboseSigstatHeader( block ) + frame; + simpleHtmlStr += frame; - if ( mSource->showSignatureDetails() ) - return htmlStr; - return simpleHtmlStr; + } else { + + // old frame settings for PGP: + + if( block.signer.isEmpty() || block.technicalProblem ) { + block.signClass = QLatin1String("signWarn"); + QString frame = QLatin1String("" + "
"); + htmlStr += frame + beginVerboseSigstatHeader(); + simpleHtmlStr += frame; + simpleHtmlStr += writeSimpleSigstatHeader( block ); + if( block.technicalProblem ) { + htmlStr += block.errorText; + } + else { + if( !block.keyId.isEmpty() ) { + QDateTime created = block.creationTime; + if ( created.isValid() ) + htmlStr += i18n( "Message was signed on %1 with unknown key %2.", + KGlobal::locale()->formatDateTime( created ), + keyWithWithoutURL ); + else + htmlStr += i18n( "Message was signed with unknown key %1.", + keyWithWithoutURL ); + } + else + htmlStr += i18n( "Message was signed with unknown key." ); + htmlStr += QLatin1String("
"); + htmlStr += i18n( "The validity of the signature cannot be " + "verified." ); + if( !statusStr.isEmpty() ) { + htmlStr += QLatin1String("
"); + htmlStr += i18n( "Status: " ); + htmlStr += QLatin1String(""); + htmlStr += statusStr; + htmlStr += QLatin1String(""); + } + } + frame = QLatin1String("
"); + htmlStr += endVerboseSigstatHeader( block ) + frame; + simpleHtmlStr += frame; + } + else + { + // HTMLize the signer's user id and create mailto: link + signer = StringUtil::quoteHtmlChars( signer, true ); + signer = QLatin1String("") + signer + QLatin1String(""); + + if (block.isGoodSignature) { + if( block.keyTrust < Kpgp::KPGP_VALIDITY_MARGINAL ) + block.signClass = QLatin1String("signOkKeyBad"); + else + block.signClass = QLatin1String("signOkKeyOk"); + QString frame = QLatin1String("" + "" + ""); + htmlStr += QLatin1String("
"); + htmlStr += frame + beginVerboseSigstatHeader(); + simpleHtmlStr += frame; + simpleHtmlStr += writeSimpleSigstatHeader( block ); + if( !block.keyId.isEmpty() ) + htmlStr += i18n( "Message was signed by %2 (Key ID: %1).", + keyWithWithoutURL, + signer ); + else + htmlStr += i18n( "Message was signed by %1.", signer ); + htmlStr += QLatin1String("
"); + + switch( block.keyTrust ) + { + case Kpgp::KPGP_VALIDITY_UNKNOWN: + htmlStr += i18n( "The signature is valid, but the key's " + "validity is unknown." ); + break; + case Kpgp::KPGP_VALIDITY_MARGINAL: + htmlStr += i18n( "The signature is valid and the key is " + "marginally trusted." ); + break; + case Kpgp::KPGP_VALIDITY_FULL: + htmlStr += i18n( "The signature is valid and the key is " + "fully trusted." ); + break; + case Kpgp::KPGP_VALIDITY_ULTIMATE: + htmlStr += i18n( "The signature is valid and the key is " + "ultimately trusted." ); + break; + default: + htmlStr += i18n( "The signature is valid, but the key is " + "untrusted." ); + } + frame = QLatin1String("
"); + htmlStr += endVerboseSigstatHeader( block ) + frame; + simpleHtmlStr += frame; + } + else + { + block.signClass = QLatin1String("signErr"); + QString frame = QLatin1String("" + "" + ""); - htmlStr += QLatin1String("
"); + htmlStr += frame + beginVerboseSigstatHeader(); + simpleHtmlStr += frame; + simpleHtmlStr += writeSimpleSigstatHeader( block ); + if( !block.keyId.isEmpty() ) + htmlStr += i18n( "Message was signed by %2 (Key ID: %1).", + keyWithWithoutURL, + signer ); + else + htmlStr += i18n( "Message was signed by %1.", signer ); + htmlStr += QLatin1String("
"); + htmlStr += i18n("Warning: The signature is bad."); + frame = QLatin1String("
"); + htmlStr += endVerboseSigstatHeader( block ) + frame; + simpleHtmlStr += frame; + } + } + } + } + + if ( mSource->showSignatureDetails() ) + return htmlStr; + return simpleHtmlStr; } QString ObjectTreeParser::writeSigstatFooter( PartMetaData& block ) { - const QString dir = ( QApplication::isRightToLeft() ? QLatin1String("rtl") : QLatin1String("ltr") ); + const QString dir = ( QApplication::isRightToLeft() ? QLatin1String("rtl") : QLatin1String("ltr") ); - QString htmlStr; + QString htmlStr; - if (block.isSigned) { - htmlStr += QLatin1String("
") + - i18n( "End of signed message" ) + - QLatin1String("
"); - } + if (block.isSigned) { + htmlStr += QLatin1String("
") + + i18n( "End of signed message" ) + + QLatin1String("
"); + } - if (block.isEncrypted) { - htmlStr += QLatin1String("
") + - i18n( "End of encrypted message" ) + - QLatin1String("
"); - } + if (block.isEncrypted) { + htmlStr += QLatin1String("
") + + i18n( "End of encrypted message" ) + + QLatin1String("
"); + } - if( block.isEncapsulatedRfc822Message ) - { - htmlStr += QLatin1String("
") + - i18n( "End of encapsulated message" ) + - QLatin1String("
"); - } + if( block.isEncapsulatedRfc822Message ) + { + htmlStr += QLatin1String("
") + + i18n( "End of encapsulated message" ) + + QLatin1String("
"); + } - return htmlStr; + return htmlStr; } @@ -2911,452 +2911,452 @@ void ObjectTreeParser::writeAttachmentMarkHeader( KMime::Content *node ) { - if ( !htmlWriter() ) - return; + if ( !htmlWriter() ) + return; - htmlWriter()->queue( QString::fromLatin1( "
\n" ).arg( node->index().toString() ) ); + htmlWriter()->queue( QString::fromLatin1( "
\n" ).arg( node->index().toString() ) ); } //----------------------------------------------------------------------------- void ObjectTreeParser::writeAttachmentMarkFooter() { - if ( !htmlWriter() ) - return; + if ( !htmlWriter() ) + return; - htmlWriter()->queue( QLatin1String( "
" ) ); + htmlWriter()->queue( QLatin1String( "
" ) ); } //----------------------------------------------------------------------------- void ObjectTreeParser::writeBodyStr( const QByteArray& aStr, const QTextCodec *aCodec, - const QString& fromAddress ) + const QString& fromAddress ) { - KMMsgSignatureState dummy1; - KMMsgEncryptionState dummy2; - writeBodyStr( aStr, aCodec, fromAddress, dummy1, dummy2, false ); + KMMsgSignatureState dummy1; + KMMsgEncryptionState dummy2; + writeBodyStr( aStr, aCodec, fromAddress, dummy1, dummy2, false ); } //----------------------------------------------------------------------------- void ObjectTreeParser::writeBodyStr( const QByteArray& aStr, const QTextCodec *aCodec, - const QString& fromAddress, - KMMsgSignatureState& inlineSignatureState, - KMMsgEncryptionState& inlineEncryptionState, - bool decorate ) -{ - const QString dir = ( QApplication::isRightToLeft() ? QLatin1String("rtl") : QLatin1String("ltr") ); - //QString headerStr = QString::fromLatin1("
").arg(dir); - - inlineSignatureState = KMMsgNotSigned; - inlineEncryptionState = KMMsgNotEncrypted; - QList pgpBlocks; - QList nonPgpBlocks; - if( Kpgp::Module::prepareMessageForDecryption( aStr, pgpBlocks, nonPgpBlocks ) ) { + const QString& fromAddress, + KMMsgSignatureState& inlineSignatureState, + KMMsgEncryptionState& inlineEncryptionState, + bool decorate ) +{ + const QString dir = ( QApplication::isRightToLeft() ? QLatin1String("rtl") : QLatin1String("ltr") ); + //QString headerStr = QString::fromLatin1("
").arg(dir); + + inlineSignatureState = KMMsgNotSigned; + inlineEncryptionState = KMMsgNotEncrypted; + QList pgpBlocks; + QList nonPgpBlocks; + if( Kpgp::Module::prepareMessageForDecryption( aStr, pgpBlocks, nonPgpBlocks ) ) { + + const Kleo::CryptoBackend::Protocol* cryptProto = Kleo::CryptoBackendFactory::instance()->openpgp(); + setCryptoProtocol( cryptProto ); + + QString htmlStr; + QString plainTextStr; + bool fullySignedOrEncrypted = true; + + QList::iterator pbit = pgpBlocks.begin(); + QListIterator npbit( nonPgpBlocks ); + + for( ; pbit != pgpBlocks.end(); ++pbit ) + { + // insert the next Non-OpenPGP block + QByteArray str( npbit.next() ); + if( !str.trimmed().isEmpty() ) { + const QString text = aCodec->toUnicode( str ); + plainTextStr += text; + if ( htmlWriter() ) { + htmlStr += quotedHTML( text, decorate ); + } + kDebug() << "Non-empty Non-OpenPGP block found: '" << str << "'"; + fullySignedOrEncrypted = false; + } - const Kleo::CryptoBackend::Protocol* cryptProto = Kleo::CryptoBackendFactory::instance()->openpgp(); - setCryptoProtocol( cryptProto ); + Kpgp::Block &block = *pbit; + KMime::Content* content = new KMime::Content; + content->setBody( block.text() ); + content->parse(); + + std::vector signatures; + bool passphraseError; + PartMetaData messagePart; + messagePart.isEncrypted = false; + messagePart.isSigned = false; + + QString text; + + if ( block.type() == Kpgp::PgpMessageBlock ) { + QByteArray decryptedData; + bool signatureFound; + bool actuallyEncrypted = true; + bool decryptionStarted; + bool bOkDecrypt = okDecryptMIME( *content, + decryptedData, + signatureFound, + signatures, + true, + passphraseError, + actuallyEncrypted, + decryptionStarted, + messagePart ); + + if ( decryptionStarted ) { + writeDecryptionInProgressBlock(); + return; + } - QString htmlStr; - QString plainTextStr; - bool fullySignedOrEncrypted = true; + messagePart.isDecryptable = bOkDecrypt; + messagePart.isEncrypted = actuallyEncrypted; + messagePart.isSigned = signatureFound; + + text = aCodec->toUnicode( decryptedData ); + + } else if ( block.type() == Kpgp::ClearsignedBlock ) { + //copied from ObjectTreeParser::writeOpaqueOrMultipartSignedData + messagePart.isSigned = false; + messagePart.technicalProblem = ( cryptProto == 0 ); + messagePart.isEncrypted = false; + messagePart.isDecryptable = false; + messagePart.keyTrust = Kpgp::KPGP_VALIDITY_UNKNOWN; + messagePart.status = i18n("Wrong Crypto Plug-In."); + messagePart.status_code = GPGME_SIG_STAT_NONE; + + Kleo::VerifyOpaqueJob * job = cryptProto->verifyOpaqueJob(); + VerifyOpaqueBodyPartMemento * m + = new VerifyOpaqueBodyPartMemento( job, cryptProto->keyListJob(), block.text() ); + m->exec(); + if ( m ) { + text = aCodec->toUnicode( m->plainText() ); + messagePart.auditLogError = m->auditLogError(); + messagePart.auditLog = m->auditLogAsHtml(); + signatures = m->verifyResult().signatures(); + messagePart.isSigned = signatures.size() > 0; + } + } - QList::iterator pbit = pgpBlocks.begin(); - QListIterator npbit( nonPgpBlocks ); - - for( ; pbit != pgpBlocks.end(); ++pbit ) - { - // insert the next Non-OpenPGP block - QByteArray str( npbit.next() ); - if( !str.trimmed().isEmpty() ) { - const QString text = aCodec->toUnicode( str ); - plainTextStr += text; - if ( htmlWriter() ) { - htmlStr += quotedHTML( text, decorate ); - } - kDebug() << "Non-empty Non-OpenPGP block found: '" << str << "'"; - fullySignedOrEncrypted = false; - } + if (!messagePart.isEncrypted && !messagePart.isSigned ) { + text = aCodec->toUnicode( block.text() ); + } - Kpgp::Block &block = *pbit; - KMime::Content* content = new KMime::Content; - content->setBody( block.text() ); - content->parse(); - - std::vector signatures; - bool passphraseError; - PartMetaData messagePart; - messagePart.isEncrypted = false; - messagePart.isSigned = false; + if ( messagePart.isEncrypted ) + inlineEncryptionState = KMMsgPartiallyEncrypted; - QString text; + if ( messagePart.isSigned ) { + inlineSignatureState = KMMsgPartiallySigned; - if ( block.type() == Kpgp::PgpMessageBlock ) { - QByteArray decryptedData; - bool signatureFound; - bool actuallyEncrypted = true; - bool decryptionStarted; - bool bOkDecrypt = okDecryptMIME( *content, - decryptedData, - signatureFound, - signatures, - true, - passphraseError, - actuallyEncrypted, - decryptionStarted, - messagePart ); + //copied from ObjectTreeParser::writeOpaqueOrMultipartSignedData + GpgME::Signature signature = signatures.front(); + GpgME::Key key; + messagePart.status_code = signatureToStatus( signature ); + messagePart.isGoodSignature = messagePart.status_code & GPGME_SIG_STAT_GOOD; + // save extended signature status flags + messagePart.sigSummary = signature.summary(); + + // Search for the key by it's fingerprint so that we can check for + // trust etc. + Kleo::KeyListJob * job = cryptProto->keyListJob( false ); // local, no sigs + if ( !job ) { + kDebug() << "The Crypto backend does not support listing keys. "; + } else { + std::vector found_keys; + // As we are local it is ok to make this synchronous + GpgME::KeyListResult res = job->exec( QStringList( QLatin1String(signature.fingerprint()) ), false, found_keys ); + if ( res.error() ) { + kDebug() << "Error while searching key for Fingerprint: " << signature.fingerprint(); + } + if ( found_keys.size() > 1 ) { + // Should not Happen + kDebug() << "Oops: Found more then one Key for Fingerprint: " << signature.fingerprint(); + } + if ( found_keys.size() != 1 ) { + // Should not Happen at this point + kDebug() << "Oops: Found no Key for Fingerprint: " << signature.fingerprint(); + } else { + key = found_keys[0]; + } + } - if ( decryptionStarted ) { - writeDecryptionInProgressBlock(); - return; - } - messagePart.isDecryptable = bOkDecrypt; - messagePart.isEncrypted = actuallyEncrypted; - messagePart.isSigned = signatureFound; + if ( key.keyID() ) { + messagePart.keyId = key.keyID(); + } + if ( messagePart.keyId.isEmpty() ) + messagePart.keyId = signature.fingerprint(); + // ### Ugh. We depend on two enums being in sync: + messagePart.keyTrust = (Kpgp::Validity)signature.validity(); + if ( key.numUserIDs() > 0 && key.userID( 0 ).id() ) + messagePart.signer = Kleo::DN( key.userID( 0 ).id() ).prettyDN(); + for ( uint iMail = 0; iMail < key.numUserIDs(); ++iMail ) { + // The following if /should/ always result in TRUE but we + // won't trust implicitely the plugin that gave us these data. + if ( key.userID( iMail ).email() ) { + QString email = QString::fromUtf8( key.userID( iMail ).email() ); + // ### work around gpgme 0.3.x / cryptplug bug where the + // ### email addresses are specified as angle-addr, not addr-spec: + if ( email.startsWith( QLatin1Char('<') ) && email.endsWith( QLatin1Char('>') ) ) + email = email.mid( 1, email.length() - 2 ); + if ( !email.isEmpty() ) + messagePart.signerMailAddresses.append( email ); + } + } - text = aCodec->toUnicode( decryptedData ); + if ( signature.creationTime() ) + messagePart.creationTime.setTime_t( signature.creationTime() ); + else + messagePart.creationTime = QDateTime(); + if ( messagePart.signer.isEmpty() ) { + if ( key.numUserIDs() > 0 && key.userID( 0 ).name() ) + messagePart.signer = Kleo::DN( key.userID( 0 ).name() ).prettyDN(); + if ( !messagePart.signerMailAddresses.empty() ) { + if ( messagePart.signer.isEmpty() ) + messagePart.signer = messagePart.signerMailAddresses.front(); + else + messagePart.signer += QLatin1String(" <") + messagePart.signerMailAddresses.front() + QLatin1Char('>'); + } + } + } - } else if ( block.type() == Kpgp::ClearsignedBlock ) { - //copied from ObjectTreeParser::writeOpaqueOrMultipartSignedData - messagePart.isSigned = false; - messagePart.technicalProblem = ( cryptProto == 0 ); - messagePart.isEncrypted = false; - messagePart.isDecryptable = false; - messagePart.keyTrust = Kpgp::KPGP_VALIDITY_UNKNOWN; - messagePart.status = i18n("Wrong Crypto Plug-In."); - messagePart.status_code = GPGME_SIG_STAT_NONE; - - Kleo::VerifyOpaqueJob * job = cryptProto->verifyOpaqueJob(); - VerifyOpaqueBodyPartMemento * m - = new VerifyOpaqueBodyPartMemento( job, cryptProto->keyListJob(), block.text() ); - m->exec(); - if ( m ) { - text = aCodec->toUnicode( m->plainText() ); - messagePart.auditLogError = m->auditLogError(); - messagePart.auditLog = m->auditLogAsHtml(); - signatures = m->verifyResult().signatures(); - messagePart.isSigned = signatures.size() > 0; - } - } + plainTextStr += text; - if (!messagePart.isEncrypted && !messagePart.isSigned ) { - text = aCodec->toUnicode( block.text() ); - } + if ( htmlWriter() ) { + if (messagePart.isEncrypted || messagePart.isSigned) + htmlStr += writeSigstatHeader( messagePart, cryptProto, fromAddress ); - if ( messagePart.isEncrypted ) - inlineEncryptionState = KMMsgPartiallyEncrypted; + if (messagePart.isEncrypted && !messagePart.isDecryptable) + htmlStr += text; //Do not quote ErrorText + else + htmlStr += quotedHTML( text, decorate ); - if ( messagePart.isSigned ) { - inlineSignatureState = KMMsgPartiallySigned; + if ( messagePart.isEncrypted || messagePart.isSigned ) + htmlStr += writeSigstatFooter( messagePart ); + } - //copied from ObjectTreeParser::writeOpaqueOrMultipartSignedData - GpgME::Signature signature = signatures.front(); - GpgME::Key key; - messagePart.status_code = signatureToStatus( signature ); - messagePart.isGoodSignature = messagePart.status_code & GPGME_SIG_STAT_GOOD; - // save extended signature status flags - messagePart.sigSummary = signature.summary(); - // Search for the key by it's fingerprint so that we can check for - // trust etc. - Kleo::KeyListJob * job = cryptProto->keyListJob( false ); // local, no sigs - if ( !job ) { - kDebug() << "The Crypto backend does not support listing keys. "; - } else { - std::vector found_keys; - // As we are local it is ok to make this synchronous - GpgME::KeyListResult res = job->exec( QStringList( QLatin1String(signature.fingerprint()) ), false, found_keys ); - if ( res.error() ) { - kDebug() << "Error while searching key for Fingerprint: " << signature.fingerprint(); - } - if ( found_keys.size() > 1 ) { - // Should not Happen - kDebug() << "Oops: Found more then one Key for Fingerprint: " << signature.fingerprint(); - } - if ( found_keys.size() != 1 ) { - // Should not Happen at this point - kDebug() << "Oops: Found no Key for Fingerprint: " << signature.fingerprint(); - } else { - key = found_keys[0]; - } } - if ( key.keyID() ) { - messagePart.keyId = key.keyID(); - } - if ( messagePart.keyId.isEmpty() ) - messagePart.keyId = signature.fingerprint(); - // ### Ugh. We depend on two enums being in sync: - messagePart.keyTrust = (Kpgp::Validity)signature.validity(); - if ( key.numUserIDs() > 0 && key.userID( 0 ).id() ) - messagePart.signer = Kleo::DN( key.userID( 0 ).id() ).prettyDN(); - for ( uint iMail = 0; iMail < key.numUserIDs(); ++iMail ) { - // The following if /should/ always result in TRUE but we - // won't trust implicitely the plugin that gave us these data. - if ( key.userID( iMail ).email() ) { - QString email = QString::fromUtf8( key.userID( iMail ).email() ); - // ### work around gpgme 0.3.x / cryptplug bug where the - // ### email addresses are specified as angle-addr, not addr-spec: - if ( email.startsWith( QLatin1Char('<') ) && email.endsWith( QLatin1Char('>') ) ) - email = email.mid( 1, email.length() - 2 ); - if ( !email.isEmpty() ) - messagePart.signerMailAddresses.append( email ); - } + // add the last Non-OpenPGP block + QByteArray str( nonPgpBlocks.last() ); + if( !str.trimmed().isEmpty() ) { + const QString text = aCodec->toUnicode( str ); + plainTextStr += text; + if ( htmlWriter() ) { + htmlStr += quotedHTML( text, decorate ); + } } - if ( signature.creationTime() ) - messagePart.creationTime.setTime_t( signature.creationTime() ); - else - messagePart.creationTime = QDateTime(); - if ( messagePart.signer.isEmpty() ) { - if ( key.numUserIDs() > 0 && key.userID( 0 ).name() ) - messagePart.signer = Kleo::DN( key.userID( 0 ).name() ).prettyDN(); - if ( !messagePart.signerMailAddresses.empty() ) { - if ( messagePart.signer.isEmpty() ) - messagePart.signer = messagePart.signerMailAddresses.front(); - else - messagePart.signer += QLatin1String(" <") + messagePart.signerMailAddresses.front() + QLatin1Char('>'); - } + //Do we have an fully Signed/Encrypted Message? + if( fullySignedOrEncrypted ) { + if( inlineSignatureState == KMMsgPartiallySigned ) + inlineSignatureState = KMMsgFullySigned; + if( inlineEncryptionState == KMMsgPartiallyEncrypted ) + inlineEncryptionState = KMMsgFullyEncrypted; } - } - - plainTextStr += text; - - if ( htmlWriter() ) { - if (messagePart.isEncrypted || messagePart.isSigned) - htmlStr += writeSigstatHeader( messagePart, cryptProto, fromAddress ); - - if (messagePart.isEncrypted && !messagePart.isDecryptable) - htmlStr += text; //Do not quote ErrorText - else - htmlStr += quotedHTML( text, decorate ); - - if ( messagePart.isEncrypted || messagePart.isSigned ) - htmlStr += writeSigstatFooter( messagePart ); - } - - - } - - // add the last Non-OpenPGP block - QByteArray str( nonPgpBlocks.last() ); - if( !str.trimmed().isEmpty() ) { - const QString text = aCodec->toUnicode( str ); - plainTextStr += text; - if ( htmlWriter() ) { - htmlStr += quotedHTML( text, decorate ); - } - } - - //Do we have an fully Signed/Encrypted Message? - if( fullySignedOrEncrypted ) { - if( inlineSignatureState == KMMsgPartiallySigned ) - inlineSignatureState = KMMsgFullySigned; - if( inlineEncryptionState == KMMsgPartiallyEncrypted ) - inlineEncryptionState = KMMsgFullyEncrypted; - } - - if ( htmlWriter() ) { - htmlWriter()->queue( htmlStr ); + if ( htmlWriter() ) { + htmlWriter()->queue( htmlStr ); + } + mPlainTextContent = plainTextStr; + mPlainTextContentCharset = aCodec->name(); } - mPlainTextContent = plainTextStr; - mPlainTextContentCharset = aCodec->name(); - } - else { // No inline PGP encryption + else { // No inline PGP encryption - const QString plainText = aCodec->toUnicode( aStr ); + const QString plainText = aCodec->toUnicode( aStr ); - if ( mPlainTextContent.isEmpty() ) { - mPlainTextContent = plainText; - mPlainTextContentCharset = aCodec->name(); - } + if ( mPlainTextContent.isEmpty() ) { + mPlainTextContent = plainText; + mPlainTextContentCharset = aCodec->name(); + } - if ( htmlWriter() ) { - htmlWriter()->queue( quotedHTML( plainText, decorate ) ); + if ( htmlWriter() ) { + htmlWriter()->queue( quotedHTML( plainText, decorate ) ); + } } - } } QString ObjectTreeParser::quotedHTML( const QString& s, bool decorate ) { - assert( cssHelper() ); + assert( cssHelper() ); - int convertFlags = LinkLocator::PreserveSpaces | LinkLocator::HighlightText; - if ( decorate && GlobalSettings::self()->showEmoticons() ) { - convertFlags |= LinkLocator::ReplaceSmileys; - } - QString htmlStr; - const QString normalStartTag = cssHelper()->nonQuotedFontTag(); - QString quoteFontTag[3]; - QString deepQuoteFontTag[3]; - for ( int i = 0 ; i < 3 ; ++i ) { - quoteFontTag[i] = cssHelper()->quoteFontTag( i ); - deepQuoteFontTag[i] = cssHelper()->quoteFontTag( i+3 ); - } - const QString normalEndTag = QLatin1String("
"); - const QString quoteEnd = QLatin1String("
"); + int convertFlags = LinkLocator::PreserveSpaces | LinkLocator::HighlightText; + if ( decorate && GlobalSettings::self()->showEmoticons() ) { + convertFlags |= LinkLocator::ReplaceSmileys; + } + QString htmlStr; + const QString normalStartTag = cssHelper()->nonQuotedFontTag(); + QString quoteFontTag[3]; + QString deepQuoteFontTag[3]; + for ( int i = 0 ; i < 3 ; ++i ) { + quoteFontTag[i] = cssHelper()->quoteFontTag( i ); + deepQuoteFontTag[i] = cssHelper()->quoteFontTag( i+3 ); + } + const QString normalEndTag = QLatin1String(""); + const QString quoteEnd = QLatin1String(""); + + const unsigned int length = s.length(); + bool paraIsRTL = false; + bool startNewPara = true; + unsigned int pos, beg; - const unsigned int length = s.length(); - bool paraIsRTL = false; - bool startNewPara = true; - unsigned int pos, beg; - - // skip leading empty lines - for ( pos = 0; pos < length && s[pos] <= QLatin1Char(' '); pos++ ) - ; - while (pos > 0 && (s[pos-1] == QLatin1Char(' ') || s[pos-1] == QLatin1Char('\t'))) pos--; - beg = pos; - - int currQuoteLevel = -2; // -2 == no previous lines - bool curHidden = false; // no hide any block - - if ( GlobalSettings::self()->showExpandQuotesMark() ) - { - // Cache Icons - if ( mCollapseIcon.isEmpty() ) { - mCollapseIcon= LinkLocator::pngToDataUrl( - IconNameCache::instance()->iconPath( QLatin1String("quotecollapse"), 0 )); - } - if ( mExpandIcon.isEmpty() ) - mExpandIcon= LinkLocator::pngToDataUrl( - IconNameCache::instance()->iconPath( QLatin1String("quoteexpand"), 0 )); - } + // skip leading empty lines + for ( pos = 0; pos < length && s[pos] <= QLatin1Char(' '); pos++ ) + ; + while (pos > 0 && (s[pos-1] == QLatin1Char(' ') || s[pos-1] == QLatin1Char('\t'))) pos--; + beg = pos; - while (beg': - case '|': - actQuoteLevel++; - break; - case ' ': // spaces and tabs are allowed between the quote markers - case '\t': - case '\r': - break; - default: // stop quoting depth calculation - p = numberOfCaracters; - break; - } - } /* for() */ + int currQuoteLevel = -2; // -2 == no previous lines + bool curHidden = false; // no hide any block - bool actHidden = false; + if ( GlobalSettings::self()->showExpandQuotesMark() ) + { + // Cache Icons + if ( mCollapseIcon.isEmpty() ) { + mCollapseIcon= LinkLocator::pngToDataUrl( + IconNameCache::instance()->iconPath( QLatin1String("quotecollapse"), 0 )); + } + if ( mExpandIcon.isEmpty() ) + mExpandIcon= LinkLocator::pngToDataUrl( + IconNameCache::instance()->iconPath( QLatin1String("quoteexpand"), 0 )); + } - // This quoted line needs be hidden - if (GlobalSettings::self()->showExpandQuotesMark() && mSource->levelQuote() >= 0 - && mSource->levelQuote() <= ( actQuoteLevel ) ) - actHidden = true; - - if ( actQuoteLevel != currQuoteLevel ) { - /* finish last quotelevel */ - if (currQuoteLevel == -1) { - htmlStr.append( normalEndTag ); - } else if ( currQuoteLevel >= 0 && !curHidden ) { - htmlStr.append( quoteEnd ); - } + while (beg': + case '|': + actQuoteLevel++; + break; + case ' ': // spaces and tabs are allowed between the quote markers + case '\t': + case '\r': + break; + default: // stop quoting depth calculation + p = numberOfCaracters; + break; + } + } /* for() */ - /* start new quotelevel */ - if (actQuoteLevel == -1) { - htmlStr += normalStartTag; - } else { - if ( GlobalSettings::self()->showExpandQuotesMark() ) { - if ( actHidden ) { - //only show the QuoteMark when is the first line of the level hidden - if ( !curHidden ) { - //Expand all quotes - htmlStr += QLatin1String("
") ; - htmlStr += QString::fromLatin1( "" - "\"\"" ) - .arg(-1) - .arg( mExpandIcon ); - htmlStr += QLatin1String("

"); - htmlStr += quoteEnd; - } - } else { - htmlStr += QLatin1String("
" ); - htmlStr += QString::fromLatin1( "" - "\"\"" ) - .arg(actQuoteLevel) - .arg( mCollapseIcon); - htmlStr += QLatin1String("
"); - if ( actQuoteLevel < 3 ) { - htmlStr += quoteFontTag[actQuoteLevel]; + bool actHidden = false; + + // This quoted line needs be hidden + if (GlobalSettings::self()->showExpandQuotesMark() && mSource->levelQuote() >= 0 + && mSource->levelQuote() <= ( actQuoteLevel ) ) + actHidden = true; + + if ( actQuoteLevel != currQuoteLevel ) { + /* finish last quotelevel */ + if (currQuoteLevel == -1) { + htmlStr.append( normalEndTag ); + } else if ( currQuoteLevel >= 0 && !curHidden ) { + htmlStr.append( quoteEnd ); + } + + /* start new quotelevel */ + if (actQuoteLevel == -1) { + htmlStr += normalStartTag; } else { - htmlStr += deepQuoteFontTag[actQuoteLevel%3]; + if ( GlobalSettings::self()->showExpandQuotesMark() ) { + if ( actHidden ) { + //only show the QuoteMark when is the first line of the level hidden + if ( !curHidden ) { + //Expand all quotes + htmlStr += QLatin1String("
") ; + htmlStr += QString::fromLatin1( "" + "\"\"" ) + .arg(-1) + .arg( mExpandIcon ); + htmlStr += QLatin1String("

"); + htmlStr += quoteEnd; + } + } else { + htmlStr += QLatin1String("
" ); + htmlStr += QString::fromLatin1( "" + "\"\"" ) + .arg(actQuoteLevel) + .arg( mCollapseIcon); + htmlStr += QLatin1String("
"); + if ( actQuoteLevel < 3 ) { + htmlStr += quoteFontTag[actQuoteLevel]; + } else { + htmlStr += deepQuoteFontTag[actQuoteLevel%3]; + } + } + } else { + if ( actQuoteLevel < 3 ) { + htmlStr += quoteFontTag[actQuoteLevel]; + } else { + htmlStr += deepQuoteFontTag[actQuoteLevel%3]; + } + } } - } - } else { - if ( actQuoteLevel < 3 ) { - htmlStr += quoteFontTag[actQuoteLevel]; - } else { - htmlStr += deepQuoteFontTag[actQuoteLevel%3]; - } + currQuoteLevel = actQuoteLevel; } - } - currQuoteLevel = actQuoteLevel; - } - curHidden = actHidden; + curHidden = actHidden; - if ( !actHidden ) - { - // don't write empty
blocks (they have zero height) - // ignore ^M DOS linebreaks - if( !line.remove( QLatin1Char('\015') ).isEmpty() ) - { - if ( startNewPara ) - paraIsRTL = line.isRightToLeft(); - htmlStr += QString::fromLatin1( "
" ).arg( paraIsRTL ? QLatin1String("rtl") : QLatin1String("ltr") ); - htmlStr += LinkLocator::convertToHtml( line, convertFlags ); - htmlStr += QLatin1String( "
" ); - startNewPara = looksLikeParaBreak( s, pos ); - } - else - { - htmlStr += QLatin1String("
"); - // after an empty line, always start a new paragraph - startNewPara = true; - } - } - } /* while() */ + if ( !actHidden ) + { + // don't write empty
blocks (they have zero height) + // ignore ^M DOS linebreaks + if( !line.remove( QLatin1Char('\015') ).isEmpty() ) + { + if ( startNewPara ) + paraIsRTL = line.isRightToLeft(); + htmlStr += QString::fromLatin1( "
" ).arg( paraIsRTL ? QLatin1String("rtl") : QLatin1String("ltr") ); + htmlStr += LinkLocator::convertToHtml( line, convertFlags ); + htmlStr += QLatin1String( "
" ); + startNewPara = looksLikeParaBreak( s, pos ); + } + else + { + htmlStr += QLatin1String("
"); + // after an empty line, always start a new paragraph + startNewPara = true; + } + } + } /* while() */ - /* really finish the last quotelevel */ - if (currQuoteLevel == -1) { - htmlStr.append( normalEndTag ); + /* really finish the last quotelevel */ + if (currQuoteLevel == -1) { + htmlStr.append( normalEndTag ); } else { - htmlStr.append( quoteEnd ); + htmlStr.append( quoteEnd ); } - //kDebug() << "========================================\n" - // << htmlStr - // << "\n======================================\n"; - return htmlStr; + //kDebug() << "========================================\n" + // << htmlStr + // << "\n======================================\n"; + return htmlStr; } const QTextCodec * ObjectTreeParser::codecFor( KMime::Content * node ) const { - assert( node ); - if ( mSource->overrideCodec() ) - return mSource->overrideCodec(); - return mNodeHelper->codec( node ); + assert( node ); + if ( mSource->overrideCodec() ) + return mSource->overrideCodec(); + return mNodeHelper->codec( node ); } // Guesstimate if the newline at newLinePos actually separates paragraphs in the text s @@ -3370,82 +3370,82 @@ // longer than the wrap size. bool ObjectTreeParser::looksLikeParaBreak( const QString& s, unsigned int newLinePos ) const { - const unsigned int WRAP_COL = 78; + const unsigned int WRAP_COL = 78; - unsigned int length = s.length(); - // 1. Is newLinePos at an end of the text? - if ( newLinePos >= length-1 || newLinePos == 0 ) { - return false; - } + unsigned int length = s.length(); + // 1. Is newLinePos at an end of the text? + if ( newLinePos >= length-1 || newLinePos == 0 ) { + return false; + } - // 2. Is the previous line really a paragraph -- longer than the wrap size? + // 2. Is the previous line really a paragraph -- longer than the wrap size? - // First char of prev line -- works also for first line - unsigned prevStart = s.lastIndexOf( QLatin1Char('\n'), newLinePos - 1 ) + 1; - unsigned prevLineLength = newLinePos - prevStart; - if ( prevLineLength > WRAP_COL ) { - return true; - } + // First char of prev line -- works also for first line + unsigned prevStart = s.lastIndexOf( QLatin1Char('\n'), newLinePos - 1 ) + 1; + unsigned prevLineLength = newLinePos - prevStart; + if ( prevLineLength > WRAP_COL ) { + return true; + } - // find next line to delimit search for first word - unsigned int nextStart = newLinePos + 1; - int nextEnd = s.indexOf( QLatin1Char('\n'), nextStart ); - if ( nextEnd == -1 ) { - nextEnd = length; - } - QString nextLine = s.mid( nextStart, nextEnd - nextStart ); - length = nextLine.length(); - // search for first word in next line - unsigned int wordStart; - bool found = false; - for ( wordStart = 0; !found && wordStart < length; wordStart++ ) { - switch ( nextLine[wordStart].toLatin1() ) { - case '>': - case '|': - case ' ': // spaces, tabs and quote markers don't count - case '\t': - case '\r': - break; - default: - found = true; - break; - } - } /* for() */ - - if ( !found ) { - // next line is essentially empty, it seems -- empty lines are - // para separators - return true; - } - //Find end of first word. - //Note: flowText (in kmmessage.cpp) separates words for wrap by - //spaces only. This should be consistent, which calls for some - //refactoring. - int wordEnd = nextLine.indexOf( QLatin1Char(' '), wordStart ); - if ( wordEnd == (-1) ) { - wordEnd = length; - } - int wordLength = wordEnd - wordStart; + // find next line to delimit search for first word + unsigned int nextStart = newLinePos + 1; + int nextEnd = s.indexOf( QLatin1Char('\n'), nextStart ); + if ( nextEnd == -1 ) { + nextEnd = length; + } + QString nextLine = s.mid( nextStart, nextEnd - nextStart ); + length = nextLine.length(); + // search for first word in next line + unsigned int wordStart; + bool found = false; + for ( wordStart = 0; !found && wordStart < length; wordStart++ ) { + switch ( nextLine[wordStart].toLatin1() ) { + case '>': + case '|': + case ' ': // spaces, tabs and quote markers don't count + case '\t': + case '\r': + break; + default: + found = true; + break; + } + } /* for() */ - // 3. If adding a space and the first word to the prev line don't - // make it reach the wrap column, then the break was probably - // meaningful - return prevLineLength + wordLength + 1 < WRAP_COL; + if ( !found ) { + // next line is essentially empty, it seems -- empty lines are + // para separators + return true; + } + //Find end of first word. + //Note: flowText (in kmmessage.cpp) separates words for wrap by + //spaces only. This should be consistent, which calls for some + //refactoring. + int wordEnd = nextLine.indexOf( QLatin1Char(' '), wordStart ); + if ( wordEnd == (-1) ) { + wordEnd = length; + } + int wordLength = wordEnd - wordStart; + + // 3. If adding a space and the first word to the prev line don't + // make it reach the wrap column, then the break was probably + // meaningful + return prevLineLength + wordLength + 1 < WRAP_COL; } #ifdef MARCS_DEBUG void ObjectTreeParser::dumpToFile( const char * filename, const char * start, - size_t len ) { - assert( filename ); + size_t len ) { + assert( filename ); - QFile f( filename ); - if ( f.open( QIODevice::WriteOnly ) ) { - if ( start ) { - QDataStream ds( &f ); - ds.writeRawData( start, len ); + QFile f( filename ); + if ( f.open( QIODevice::WriteOnly ) ) { + if ( start ) { + QDataStream ds( &f ); + ds.writeRawData( start, len ); + } + f.close(); // If data is 0 we just create a zero length file. } - f.close(); // If data is 0 we just create a zero length file. - } } #endif // !NDEBUG @@ -3453,7 +3453,7 @@ KMime::Content* ObjectTreeParser::findType( KMime::Content* content, const QByteArray& mimeType, bool deep, bool wide ) { if( ( !content->contentType()->isEmpty() ) - && ( mimeType.isEmpty() || ( mimeType == content->contentType()->mimeType() ) ) ) + && ( mimeType.isEmpty() || ( mimeType == content->contentType()->mimeType() ) ) ) return content; KMime::Content *child = MessageCore::NodeHelper::firstChild( content ); if ( child && deep ) //first child @@ -3461,7 +3461,7 @@ KMime::Content *next = MessageCore::NodeHelper::nextSibling( content ); if (next && wide ) //next on the same level - return findType( next, mimeType, deep, wide ); + return findType( next, mimeType, deep, wide ); return 0; } @@ -3469,9 +3469,9 @@ KMime::Content* ObjectTreeParser::findType( KMime::Content* content, const QByteArray& mediaType, const QByteArray& subType, bool deep, bool wide ) { if ( !content->contentType()->isEmpty() ) { - if ( ( mediaType.isEmpty() || mediaType == content->contentType()->mediaType() ) - && ( subType.isEmpty() || subType == content->contentType()->subType() ) ) - return content; + if ( ( mediaType.isEmpty() || mediaType == content->contentType()->mediaType() ) + && ( subType.isEmpty() || subType == content->contentType()->subType() ) ) + return content; } KMime::Content *child = MessageCore::NodeHelper::firstChild( content ); if ( child && deep ) //first child @@ -3479,7 +3479,7 @@ KMime::Content *next = MessageCore::NodeHelper::nextSibling( content ); if (next && wide ) //next on the same level - return findType( next, mediaType, subType, deep, wide ); + return findType( next, mediaType, subType, deep, wide ); return 0; } @@ -3487,9 +3487,9 @@ KMime::Content* ObjectTreeParser::findTypeNot( KMime::Content * content, const QByteArray& mediaType, const QByteArray& subType, bool deep, bool wide ) { if( ( !content->contentType()->isEmpty() ) - && ( mediaType.isEmpty() || content->contentType()->mediaType() != mediaType ) - && ( subType.isEmpty() || content->contentType()->subType() != subType ) - ) + && ( mediaType.isEmpty() || content->contentType()->mediaType() != mediaType ) + && ( subType.isEmpty() || content->contentType()->subType() != subType ) + ) return content; KMime::Content *child = MessageCore::NodeHelper::firstChild( content ); if ( child && deep ) @@ -3503,29 +3503,29 @@ QString ObjectTreeParser::convertedTextContent() const { - QString plainTextContent = mPlainTextContent; - if( plainTextContent.isEmpty() ) { + QString plainTextContent = mPlainTextContent; + if( plainTextContent.isEmpty() ) { #ifdef KDEPIM_NO_WEBKIT - QTextDocument doc; - doc.setHtml( mHtmlContent ); - plainTextContent = doc.toPlainText(); + QTextDocument doc; + doc.setHtml( mHtmlContent ); + plainTextContent = doc.toPlainText(); #else - QWebPage doc; - doc.mainFrame()->setHtml( mHtmlContent ); - plainTextContent = doc.mainFrame()->toPlainText(); + QWebPage doc; + doc.mainFrame()->setHtml( mHtmlContent ); + plainTextContent = doc.mainFrame()->toPlainText(); #endif - } - return plainTextContent.append(QLatin1Char('\n')); + } + return plainTextContent.append(QLatin1Char('\n')); } QString ObjectTreeParser::convertedHtmlContent() const { - QString htmlContent = mHtmlContent; - if( htmlContent.isEmpty() ) { - QString convertedHtml = Qt::escape( mPlainTextContent ); - convertedHtml.append(QLatin1String("")); - convertedHtml.prepend(QLatin1String("")); - htmlContent = convertedHtml.replace( QRegExp( QLatin1String("\n" )), QLatin1String("
") ); - } - return htmlContent.append(QLatin1Char('\n')); + QString htmlContent = mHtmlContent; + if( htmlContent.isEmpty() ) { + QString convertedHtml = Qt::escape( mPlainTextContent ); + convertedHtml.append(QLatin1String("")); + convertedHtml.prepend(QLatin1String("")); + htmlContent = convertedHtml.replace( QRegExp( QLatin1String("\n" )), QLatin1String("
") ); + } + return htmlContent.append(QLatin1Char('\n')); } diff -Nru kdepim-4.12.97/messageviewer/viewer/objecttreeparser.h kdepim-4.13.0/messageviewer/viewer/objecttreeparser.h --- kdepim-4.12.97/messageviewer/viewer/objecttreeparser.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/objecttreeparser.h 2014-04-10 07:40:20.000000000 +0000 @@ -48,12 +48,12 @@ class QString; namespace KMime { - class Content; +class Content; } namespace GpgME { - class Error; - class ImportResult; +class Error; +class ImportResult; } @@ -68,48 +68,48 @@ class ProcessResult { public: - explicit ProcessResult( NodeHelper *nodeHelper, KMMsgSignatureState inlineSignatureState = KMMsgNotSigned, - KMMsgEncryptionState inlineEncryptionState = KMMsgNotEncrypted, - bool neverDisplayInline = false, - bool isImage = false ) - : mInlineSignatureState( inlineSignatureState ), - mInlineEncryptionState( inlineEncryptionState ), - mNeverDisplayInline( neverDisplayInline ), - mIsImage( isImage ), - mNodeHelper( nodeHelper ) {} - - KMMsgSignatureState inlineSignatureState() const { - return mInlineSignatureState; - } - void setInlineSignatureState( KMMsgSignatureState state ) { - mInlineSignatureState = state; - } - - KMMsgEncryptionState inlineEncryptionState() const { - return mInlineEncryptionState; - } - void setInlineEncryptionState( KMMsgEncryptionState state ) { - mInlineEncryptionState = state; - } - - bool neverDisplayInline() const { return mNeverDisplayInline; } - void setNeverDisplayInline( bool display ) { - mNeverDisplayInline = display; - } - - bool isImage() const { return mIsImage; } - void setIsImage( bool image ) { - mIsImage = image; - } + explicit ProcessResult( NodeHelper *nodeHelper, KMMsgSignatureState inlineSignatureState = KMMsgNotSigned, + KMMsgEncryptionState inlineEncryptionState = KMMsgNotEncrypted, + bool neverDisplayInline = false, + bool isImage = false ) + : mInlineSignatureState( inlineSignatureState ), + mInlineEncryptionState( inlineEncryptionState ), + mNeverDisplayInline( neverDisplayInline ), + mIsImage( isImage ), + mNodeHelper( nodeHelper ) {} + + KMMsgSignatureState inlineSignatureState() const { + return mInlineSignatureState; + } + void setInlineSignatureState( KMMsgSignatureState state ) { + mInlineSignatureState = state; + } + + KMMsgEncryptionState inlineEncryptionState() const { + return mInlineEncryptionState; + } + void setInlineEncryptionState( KMMsgEncryptionState state ) { + mInlineEncryptionState = state; + } + + bool neverDisplayInline() const { return mNeverDisplayInline; } + void setNeverDisplayInline( bool display ) { + mNeverDisplayInline = display; + } + + bool isImage() const { return mIsImage; } + void setIsImage( bool image ) { + mIsImage = image; + } - void adjustCryptoStatesOfNode( KMime::Content * node ) const; + void adjustCryptoStatesOfNode( KMime::Content * node ) const; private: - KMMsgSignatureState mInlineSignatureState; - KMMsgEncryptionState mInlineEncryptionState; - bool mNeverDisplayInline : 1; - bool mIsImage : 1; - NodeHelper* mNodeHelper; + KMMsgSignatureState mInlineSignatureState; + KMMsgEncryptionState mInlineEncryptionState; + bool mNeverDisplayInline : 1; + bool mIsImage : 1; + NodeHelper* mNodeHelper; }; /** @@ -285,33 +285,33 @@ the Viewer to scroll to the attachment. */ class MESSAGEVIEWER_EXPORT ObjectTreeParser { - class CryptoProtocolSaver; - /** + class CryptoProtocolSaver; + /** * @internal * Copies the context of @p other, but not it's rawDecryptedBody, plainTextContent or htmlContent. */ - ObjectTreeParser( const ObjectTreeParser & other ); + ObjectTreeParser( const ObjectTreeParser & other ); public: - explicit ObjectTreeParser( ObjectTreeSourceIf * source, - NodeHelper *nodeHelper = 0, - const Kleo::CryptoBackend::Protocol * protocol=0, - bool showOneMimePart=false, bool keepEncryptions=false, - bool includeSignatures=true, - const AttachmentStrategy * attachmentStrategy=0 ); - - explicit ObjectTreeParser( const ObjectTreeParser *topLevelParser, - bool showOneMimePart=false, bool keepEncryptions=false, - bool includeSignatures=true, - const AttachmentStrategy * attachmentStrategy=0 ); - virtual ~ObjectTreeParser(); + explicit ObjectTreeParser( ObjectTreeSourceIf * source, + NodeHelper *nodeHelper = 0, + const Kleo::CryptoBackend::Protocol * protocol=0, + bool showOneMimePart=false, bool keepEncryptions=false, + bool includeSignatures=true, + const AttachmentStrategy * attachmentStrategy=0 ); + + explicit ObjectTreeParser( const ObjectTreeParser *topLevelParser, + bool showOneMimePart=false, bool keepEncryptions=false, + bool includeSignatures=true, + const AttachmentStrategy * attachmentStrategy=0 ); + virtual ~ObjectTreeParser(); - void setAllowAsync( bool allow ) { assert( !mHasPendingAsyncJobs ); mAllowAsync = allow; } - bool allowAsync() const { return mAllowAsync; } + void setAllowAsync( bool allow ) { assert( !mHasPendingAsyncJobs ); mAllowAsync = allow; } + bool allowAsync() const { return mAllowAsync; } - bool hasPendingAsyncJobs() const { return mHasPendingAsyncJobs; } + bool hasPendingAsyncJobs() const { return mHasPendingAsyncJobs; } - /** + /** * The origin and purpose of this function is unknown, the ancient wisdom about it got lost during * the centuries. * @@ -327,110 +327,110 @@ * * Do not use. Use plainTextContent() and htmlContent() instead. */ - KDE_DEPRECATED QByteArray rawDecryptedBody() const { return mRawDecryptedBody; } + KDE_DEPRECATED QByteArray rawDecryptedBody() const { return mRawDecryptedBody; } - /** + /** * The text of the message, ie. what would appear in the * composer's text editor if this was edited or replied to. * This is usually the content of the first text/plain MIME part. - */ - QString plainTextContent() const { return mPlainTextContent; } + */ + QString plainTextContent() const { return mPlainTextContent; } - /** + /** * Similar to plainTextContent(), but returns the HTML source of the first text/html MIME part. * * Not to be consfused with the HTML code that the message viewer widget displays, that HTML * is written out by htmlWriter() and a totally different pair of shoes. */ - QString htmlContent() const { return mHtmlContent; } + QString htmlContent() const { return mHtmlContent; } - /** + /** * Returns a plain text version of the content, which is either plainTextContent() if that exists, * or htmlContent() converted to plain text otherwise. */ - QString convertedTextContent() const; + QString convertedTextContent() const; - /** Returns a HTML version of the plain text mail. If the HTML content is already available, it + /** Returns a HTML version of the plain text mail. If the HTML content is already available, it * returns the HTML content as it is. */ - QString convertedHtmlContent() const; + QString convertedHtmlContent() const; - /** + /** * The original charset of MIME part the plain text was extracted from. * * If there were more than one text/plain MIME parts in the mail, the this is the charset * of the last MIME part processed. */ - QByteArray plainTextContentCharset() const { return mPlainTextContentCharset; } - QByteArray htmlContentCharset() const { return mHtmlContentCharset; } + QByteArray plainTextContentCharset() const { return mPlainTextContentCharset; } + QByteArray htmlContentCharset() const { return mHtmlContentCharset; } - void setCryptoProtocol( const Kleo::CryptoBackend::Protocol * protocol ) { - mCryptoProtocol = protocol; - } - const Kleo::CryptoBackend::Protocol* cryptoProtocol() const { - return mCryptoProtocol; - } - - bool showOnlyOneMimePart() const { return mShowOnlyOneMimePart; } - void setShowOnlyOneMimePart( bool show ) { - mShowOnlyOneMimePart = show; - } - - bool keepEncryptions() const { return mKeepEncryptions; } - void setKeepEncryptions( bool keep ) { - mKeepEncryptions = keep; - } - - bool includeSignatures() const { return mIncludeSignatures; } - void setIncludeSignatures( bool include ) { - mIncludeSignatures = include; - } - - // Controls whether Toltec invitations are displayed in their raw form or as a replacement text, - // which is used in processToltecMail(). - void setShowRawToltecMail( bool showRawToltecMail ) { mShowRawToltecMail = showRawToltecMail; } - bool showRawToltecMail() const { return mShowRawToltecMail; } - - /// Default text for processToltecMail(), which is used in messageviewer.kcfg, therefore it - /// needs to be static here. - static QString defaultToltecReplacementText(); - - const AttachmentStrategy * attachmentStrategy() const { - return mAttachmentStrategy; - } + void setCryptoProtocol( const Kleo::CryptoBackend::Protocol * protocol ) { + mCryptoProtocol = protocol; + } + const Kleo::CryptoBackend::Protocol* cryptoProtocol() const { + return mCryptoProtocol; + } + + bool showOnlyOneMimePart() const { return mShowOnlyOneMimePart; } + void setShowOnlyOneMimePart( bool show ) { + mShowOnlyOneMimePart = show; + } + + bool keepEncryptions() const { return mKeepEncryptions; } + void setKeepEncryptions( bool keep ) { + mKeepEncryptions = keep; + } + + bool includeSignatures() const { return mIncludeSignatures; } + void setIncludeSignatures( bool include ) { + mIncludeSignatures = include; + } + + // Controls whether Toltec invitations are displayed in their raw form or as a replacement text, + // which is used in processToltecMail(). + void setShowRawToltecMail( bool showRawToltecMail ) { mShowRawToltecMail = showRawToltecMail; } + bool showRawToltecMail() const { return mShowRawToltecMail; } + + /// Default text for processToltecMail(), which is used in messageviewer.kcfg, therefore it + /// needs to be static here. + static QString defaultToltecReplacementText(); + + const AttachmentStrategy * attachmentStrategy() const { + return mAttachmentStrategy; + } - HtmlWriter * htmlWriter() const { return mSource->htmlWriter(); } + HtmlWriter * htmlWriter() const { return mSource->htmlWriter(); } - CSSHelper * cssHelper() const { return mSource->cssHelper(); } + CSSHelper * cssHelper() const { return mSource->cssHelper(); } - NodeHelper * nodeHelper() const { return mNodeHelper; } + NodeHelper * nodeHelper() const { return mNodeHelper; } - /** Parse beginning at a given node and recursively parsing + /** Parse beginning at a given node and recursively parsing the children of that node and it's next sibling. */ - void parseObjectTree( KMime::Content * node ); + void parseObjectTree( KMime::Content * node ); private: - void extractNodeInfos( KMime::Content *curNode, bool isFirstTextPart ); + void extractNodeInfos( KMime::Content *curNode, bool isFirstTextPart ); - /** + /** * Does the actual work for parseObjectTree. Unlike parseObjectTree(), this does not change the * top-level content. */ - void parseObjectTreeInternal( KMime::Content * node ); + void parseObjectTreeInternal( KMime::Content * node ); - /** Standard children handling a.k.a. multipart/mixed (w/o + /** Standard children handling a.k.a. multipart/mixed (w/o kroupware hacks) */ - void stdChildHandling( KMime::Content * child ); + void stdChildHandling( KMime::Content * child ); - void defaultHandling( KMime::Content * node, ProcessResult & result ); + void defaultHandling( KMime::Content * node, ProcessResult & result ); - /** 1. Create a new partNode using 'content' data and Content-Description + /** 1. Create a new partNode using 'content' data and Content-Description found in 'cntDesc'. 2. Parse the 'node' to display the content. */ - void createAndParseTempNode( KMime::Content* parentNode, const char * content, const char * cntDesc ); + void createAndParseTempNode( KMime::Content* parentNode, const char * content, const char * cntDesc ); - /** if data is 0: + /** if data is 0: Feeds the HTML widget with the contents of the opaque signed data found in partNode 'sign'. if data is set: @@ -440,39 +440,39 @@ Returns whether a signature was found or not: use this to find out if opaque data is signed or not. */ - bool writeOpaqueOrMultipartSignedData( KMime::Content * data, - KMime::Content & sign, - const QString & fromAddress, - bool doCheck=true, - QByteArray * cleartextData=0, - const std::vector & paramSignatures = std::vector(), - bool hideErrors=false ); + bool writeOpaqueOrMultipartSignedData( KMime::Content * data, + KMime::Content & sign, + const QString & fromAddress, + bool doCheck=true, + QByteArray * cleartextData=0, + const std::vector & paramSignatures = std::vector(), + bool hideErrors=false ); - /** Writes out the block that we use when the node is encrypted, + /** Writes out the block that we use when the node is encrypted, but we're deferring decryption for later. */ - void writeDeferredDecryptionBlock(); + void writeDeferredDecryptionBlock(); - /** Writes out the block that we use when the node is encrypted, + /** Writes out the block that we use when the node is encrypted, but we've just kicked off async decryption. */ - void writeDecryptionInProgressBlock(); + void writeDecryptionInProgressBlock(); - /** Writes out the information contained in a GpgME::ImportResult */ - void writeCertificateImportResult( const GpgME::ImportResult & res ); + /** Writes out the information contained in a GpgME::ImportResult */ + void writeCertificateImportResult( const GpgME::ImportResult & res ); - /** Returns the contents of the given multipart/encrypted + /** Returns the contents of the given multipart/encrypted object. Data is decypted. May contain body parts. */ - bool okDecryptMIME( KMime::Content& data, - QByteArray& decryptedData, - bool& signatureFound, - std::vector &signatures, - bool showWarning, - bool& passphraseError, - bool& actuallyEncrypted, - bool& decryptionStarted, - PartMetaData &partMetaData ); + bool okDecryptMIME( KMime::Content& data, + QByteArray& decryptedData, + bool& signatureFound, + std::vector &signatures, + bool showWarning, + bool& passphraseError, + bool& actuallyEncrypted, + bool& decryptionStarted, + PartMetaData &partMetaData ); - /** + /** * This is called for all multipart/mixed nodes. It checks if that belongs to a Toltec mail, * by checking various criteria. * If it is a toltec mail, a special text, instead of the confusing toltec text, will be @@ -481,136 +481,136 @@ * @return true if the mail was indeed a toltec mail, in which case the node should not be * processed further */ - bool processToltecMail( KMime::Content *node ); + bool processToltecMail( KMime::Content *node ); - bool processMailmanMessage( KMime::Content* node ); + bool processMailmanMessage( KMime::Content* node ); - /** Checks whether @p str contains external references. To be precise, + /** Checks whether @p str contains external references. To be precise, we only check whether @p str contains 'xxx="http[s]:' where xxx is not href. Obfuscated external references are ignored on purpose. */ - static bool containsExternalReferences(const QString & str , const QString &extraHead); + static bool containsExternalReferences(const QString & str , const QString &extraHead); public:// (during refactoring) - bool processTextHtmlSubtype( KMime::Content * node, ProcessResult & result ); - bool processTextPlainSubtype( KMime::Content *node, ProcessResult & result ); + bool processTextHtmlSubtype( KMime::Content * node, ProcessResult & result ); + bool processTextPlainSubtype( KMime::Content *node, ProcessResult & result ); - bool processMultiPartMixedSubtype( KMime::Content * node, ProcessResult & result ); - bool processMultiPartAlternativeSubtype( KMime::Content * node, ProcessResult & result ); - bool processMultiPartDigestSubtype( KMime::Content * node, ProcessResult & result ); - bool processMultiPartParallelSubtype( KMime::Content * node, ProcessResult & result ); - bool processMultiPartSignedSubtype( KMime::Content * node, ProcessResult & result ); - bool processMultiPartEncryptedSubtype( KMime::Content * node, ProcessResult & result ); - - bool processMessageRfc822Subtype( KMime::Content * node, ProcessResult & result ); - - bool processApplicationOctetStreamSubtype( KMime::Content * node, ProcessResult & result ); - bool processApplicationPkcs7MimeSubtype( KMime::Content * node, ProcessResult & result ); - bool processApplicationChiasmusTextSubtype( KMime::Content * node, ProcessResult & result ); - - bool decryptChiasmus( const QByteArray& data, QByteArray& bodyDecoded, QString& errorText ); - void writeBodyString( const QByteArray & bodyString, - const QString & fromAddress, - const QTextCodec * codec, - ProcessResult & result, bool decorate ); - - void writePartIcon( KMime::Content * msgPart, bool inlineImage = false ); - - QString sigStatusToString( const Kleo::CryptoBackend::Protocol * cryptProto, - int status_code, - GpgME::Signature::Summary summary, - int & frameColor, - bool & showKeyInfos ); - QString writeSigstatHeader( PartMetaData & part, - const Kleo::CryptoBackend::Protocol * cryptProto, - const QString & fromAddress, - KMime::Content *node = 0); - QString writeSigstatFooter( PartMetaData & part ); - - // The attachment mark is a div that is placed around the attchment. It is used for drawing - // a yellow border around the attachment when scrolling to it. When scrolling to it, the border - // color of the div is changed, see KMReaderWin::scrollToAttachment(). - void writeAttachmentMarkHeader( KMime::Content *node ); - void writeAttachmentMarkFooter(); - - void writeBodyStr( const QByteArray & bodyString, - const QTextCodec * aCodec, - const QString & fromAddress, - KMMsgSignatureState & inlineSignatureState, - KMMsgEncryptionState & inlineEncryptionState, - bool decorate ); + bool processMultiPartMixedSubtype( KMime::Content * node, ProcessResult & result ); + bool processMultiPartAlternativeSubtype( KMime::Content * node, ProcessResult & result ); + bool processMultiPartDigestSubtype( KMime::Content * node, ProcessResult & result ); + bool processMultiPartParallelSubtype( KMime::Content * node, ProcessResult & result ); + bool processMultiPartSignedSubtype( KMime::Content * node, ProcessResult & result ); + bool processMultiPartEncryptedSubtype( KMime::Content * node, ProcessResult & result ); + + bool processMessageRfc822Subtype( KMime::Content * node, ProcessResult & result ); + + bool processApplicationOctetStreamSubtype( KMime::Content * node, ProcessResult & result ); + bool processApplicationPkcs7MimeSubtype( KMime::Content * node, ProcessResult & result ); + bool processApplicationChiasmusTextSubtype( KMime::Content * node, ProcessResult & result ); + + bool decryptChiasmus( const QByteArray& data, QByteArray& bodyDecoded, QString& errorText ); + void writeBodyString( const QByteArray & bodyString, + const QString & fromAddress, + const QTextCodec * codec, + ProcessResult & result, bool decorate ); + + void writePartIcon( KMime::Content * msgPart, bool inlineImage = false ); + + QString sigStatusToString( const Kleo::CryptoBackend::Protocol * cryptProto, + int status_code, + GpgME::Signature::Summary summary, + int & frameColor, + bool & showKeyInfos ); + QString writeSigstatHeader( PartMetaData & part, + const Kleo::CryptoBackend::Protocol * cryptProto, + const QString & fromAddress, + KMime::Content *node = 0); + QString writeSigstatFooter( PartMetaData & part ); + + // The attachment mark is a div that is placed around the attchment. It is used for drawing + // a yellow border around the attachment when scrolling to it. When scrolling to it, the border + // color of the div is changed, see KMReaderWin::scrollToAttachment(). + void writeAttachmentMarkHeader( KMime::Content *node ); + void writeAttachmentMarkFooter(); + + void writeBodyStr( const QByteArray & bodyString, + const QTextCodec * aCodec, + const QString & fromAddress, + KMMsgSignatureState & inlineSignatureState, + KMMsgEncryptionState & inlineEncryptionState, + bool decorate ); - bool isMailmanMessage( KMime::Content * curNode ); + bool isMailmanMessage( KMime::Content * curNode ); public: // KMReaderWin still needs this... - void writeBodyStr( const QByteArray & bodyString, - const QTextCodec * aCodec, - const QString & fromAddress ); - static KMime::Content* findType( KMime::Content* content, const QByteArray& mimeType, bool deep, bool wide ); + void writeBodyStr( const QByteArray & bodyString, + const QTextCodec * aCodec, + const QString & fromAddress ); + static KMime::Content* findType( KMime::Content* content, const QByteArray& mimeType, bool deep, bool wide ); - static KMime::Content* findType( KMime::Content* content, const QByteArray& mediaType, const QByteArray& subType, bool deep, bool wide ); + static KMime::Content* findType( KMime::Content* content, const QByteArray& mediaType, const QByteArray& subType, bool deep, bool wide ); - static KMime::Content* findTypeNot( KMime::Content* content, const QByteArray& mediaType, const QByteArray& subType, bool deep=true, bool wide=true ); + static KMime::Content* findTypeNot( KMime::Content* content, const QByteArray& mediaType, const QByteArray& subType, bool deep=true, bool wide=true ); private: - /** ctor helper */ - void init(); + /** ctor helper */ + void init(); - /** Change the string to `quoted' html (meaning, that the quoted + /** Change the string to `quoted' html (meaning, that the quoted part of the message get italized */ - QString quotedHTML(const QString& pos, bool decorate); + QString quotedHTML(const QString& pos, bool decorate); - const QTextCodec * codecFor( KMime::Content * node ) const; - /** Check if the newline at position @p newLinePos in string @p s + const QTextCodec * codecFor( KMime::Content * node ) const; + /** Check if the newline at position @p newLinePos in string @p s seems to separate two paragraphs (important for correct BiDi behavior, but is heuristic because paragraphs are not well-defined) */ - bool looksLikeParaBreak(const QString& s, unsigned int newLinePos) const; + bool looksLikeParaBreak(const QString& s, unsigned int newLinePos) const; #ifdef MARCS_DEBUG - void dumpToFile( const char * filename, const char * dataStart, size_t dataLen ); + void dumpToFile( const char * filename, const char * dataStart, size_t dataLen ); #else - void dumpToFile( const char *, const char *, size_t ) {} + void dumpToFile( const char *, const char *, size_t ) {} #endif - void copyContentFrom( const ObjectTreeParser *other ); + void copyContentFrom( const ObjectTreeParser *other ); private: - ObjectTreeSourceIf* mSource; - NodeHelper* mNodeHelper; - QByteArray mRawDecryptedBody; - QByteArray mPlainTextContentCharset; - QByteArray mHtmlContentCharset; - QString mPlainTextContent; - QString mHtmlContent; - KMime::Content *mTopLevelContent; - const Kleo::CryptoBackend::Protocol * mCryptoProtocol; - - /// Show only one mime part means that the user has selected some node in the message structure - /// viewer that is not the root, which means the user wants to only see the selected node and its - /// children. If that is the case, this variable is set to true. - /// The code needs to behave differently if this is set. For example, it should not process the - /// siblings. Also, consider inline images: Normally, those nodes are completely hidden, as the - /// HTML node embedds them. However, when showing only the node of the image, one has to show them, - /// as their is no HTML node in which they are displayed. There are many more cases where this - /// variable needs to be obeyed. - /// This variable is set to false again when processing the children in stdChildHandling(), as - /// the children can be completely displayed again. - bool mShowOnlyOneMimePart; - - bool mKeepEncryptions; - bool mIncludeSignatures; - bool mHasPendingAsyncJobs; - bool mAllowAsync; - bool mShowRawToltecMail; - const AttachmentStrategy * mAttachmentStrategy; - // DataUrl Icons cache - QString mCollapseIcon; - QString mExpandIcon; - bool mDeleteNodeHelper; + ObjectTreeSourceIf* mSource; + NodeHelper* mNodeHelper; + QByteArray mRawDecryptedBody; + QByteArray mPlainTextContentCharset; + QByteArray mHtmlContentCharset; + QString mPlainTextContent; + QString mHtmlContent; + KMime::Content *mTopLevelContent; + const Kleo::CryptoBackend::Protocol * mCryptoProtocol; + + /// Show only one mime part means that the user has selected some node in the message structure + /// viewer that is not the root, which means the user wants to only see the selected node and its + /// children. If that is the case, this variable is set to true. + /// The code needs to behave differently if this is set. For example, it should not process the + /// siblings. Also, consider inline images: Normally, those nodes are completely hidden, as the + /// HTML node embedds them. However, when showing only the node of the image, one has to show them, + /// as their is no HTML node in which they are displayed. There are many more cases where this + /// variable needs to be obeyed. + /// This variable is set to false again when processing the children in stdChildHandling(), as + /// the children can be completely displayed again. + bool mShowOnlyOneMimePart; + + bool mKeepEncryptions; + bool mIncludeSignatures; + bool mHasPendingAsyncJobs; + bool mAllowAsync; + bool mShowRawToltecMail; + const AttachmentStrategy * mAttachmentStrategy; + // DataUrl Icons cache + QString mCollapseIcon; + QString mExpandIcon; + bool mDeleteNodeHelper; }; diff -Nru kdepim-4.12.97/messageviewer/viewer/objecttreeparser_p.cpp kdepim-4.13.0/messageviewer/viewer/objecttreeparser_p.cpp --- kdepim-4.12.97/messageviewer/viewer/objecttreeparser_p.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/objecttreeparser_p.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -54,9 +54,9 @@ using namespace MessageViewer; CryptoBodyPartMemento::CryptoBodyPartMemento() - : QObject( 0 ), - Interface::BodyPartMemento(), - m_running( false ) + : QObject( 0 ), + Interface::BodyPartMemento(), + m_running( false ) { } @@ -64,73 +64,73 @@ CryptoBodyPartMemento::~CryptoBodyPartMemento() {} void CryptoBodyPartMemento::setAuditLog( const Error & err, const QString & log ) { - m_auditLogError = err; - m_auditLog = log; + m_auditLogError = err; + m_auditLog = log; } void CryptoBodyPartMemento::setRunning( bool running ) { - m_running = running; + m_running = running; } void CryptoBodyPartMemento::detach() { - disconnect( this, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), 0, 0 ); + disconnect( this, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), 0, 0 ); } DecryptVerifyBodyPartMemento::DecryptVerifyBodyPartMemento( DecryptVerifyJob * job, const QByteArray & cipherText ) - : CryptoBodyPartMemento(), - m_cipherText( cipherText ), - m_job( job ) + : CryptoBodyPartMemento(), + m_cipherText( cipherText ), + m_job( job ) { - assert( m_job ); + assert( m_job ); } DecryptVerifyBodyPartMemento::~DecryptVerifyBodyPartMemento() { - if ( m_job ) - m_job->slotCancel(); + if ( m_job ) + m_job->slotCancel(); } bool DecryptVerifyBodyPartMemento::start() { - assert( m_job ); - if ( const Error err = m_job->start( m_cipherText ) ) { - m_dr = DecryptionResult( err ); - return false; - } - connect( m_job, SIGNAL(result(GpgME::DecryptionResult,GpgME::VerificationResult,QByteArray)), - this, SLOT(slotResult(GpgME::DecryptionResult,GpgME::VerificationResult,QByteArray)) ); - setRunning( true ); - return true; + assert( m_job ); + if ( const Error err = m_job->start( m_cipherText ) ) { + m_dr = DecryptionResult( err ); + return false; + } + connect( m_job, SIGNAL(result(GpgME::DecryptionResult,GpgME::VerificationResult,QByteArray)), + this, SLOT(slotResult(GpgME::DecryptionResult,GpgME::VerificationResult,QByteArray)) ); + setRunning( true ); + return true; } void DecryptVerifyBodyPartMemento::exec() { - assert( m_job ); - QByteArray plainText; - setRunning( true ); - const std::pair p = m_job->exec( m_cipherText, plainText ); - saveResult( p.first, p.second, plainText ); - m_job->deleteLater(); // exec'ed jobs don't delete themselves - m_job = 0; + assert( m_job ); + QByteArray plainText; + setRunning( true ); + const std::pair p = m_job->exec( m_cipherText, plainText ); + saveResult( p.first, p.second, plainText ); + m_job->deleteLater(); // exec'ed jobs don't delete themselves + m_job = 0; } void DecryptVerifyBodyPartMemento::saveResult( const DecryptionResult & dr, const VerificationResult & vr, const QByteArray & plainText ) { - assert( m_job ); - setRunning( false ); - m_dr = dr; - m_vr = vr; - m_plainText = plainText; - setAuditLog( m_job->auditLogError(), m_job->auditLogAsHtml() ); + assert( m_job ); + setRunning( false ); + m_dr = dr; + m_vr = vr; + m_plainText = plainText; + setAuditLog( m_job->auditLogError(), m_job->auditLogAsHtml() ); } void DecryptVerifyBodyPartMemento::slotResult( const DecryptionResult & dr, const VerificationResult & vr, const QByteArray & plainText ) { - saveResult( dr, vr, plainText ); - m_job = 0; - notify(); + saveResult( dr, vr, plainText ); + m_job = 0; + notify(); } @@ -140,272 +140,272 @@ KeyListJob * klj, const QByteArray & signature, const QByteArray & plainText ) - : CryptoBodyPartMemento(), - m_signature( signature ), - m_plainText( plainText ), - m_job( job ), - m_keylistjob( klj ) + : CryptoBodyPartMemento(), + m_signature( signature ), + m_plainText( plainText ), + m_job( job ), + m_keylistjob( klj ) { - assert( m_job ); + assert( m_job ); } VerifyDetachedBodyPartMemento::~VerifyDetachedBodyPartMemento() { - if ( m_job ) - m_job->slotCancel(); - if ( m_keylistjob ) - m_keylistjob->slotCancel(); + if ( m_job ) + m_job->slotCancel(); + if ( m_keylistjob ) + m_keylistjob->slotCancel(); } bool VerifyDetachedBodyPartMemento::start() { - assert( m_job ); + assert( m_job ); #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyDetachedBodyPartMemento started"; + kDebug() << "tokoe: VerifyDetachedBodyPartMemento started"; #endif - connect( m_job, SIGNAL(result(GpgME::VerificationResult)), - this, SLOT(slotResult(GpgME::VerificationResult)) ); - if ( const Error err = m_job->start( m_signature, m_plainText ) ) { - m_vr = VerificationResult( err ); + connect( m_job, SIGNAL(result(GpgME::VerificationResult)), + this, SLOT(slotResult(GpgME::VerificationResult)) ); + if ( const Error err = m_job->start( m_signature, m_plainText ) ) { + m_vr = VerificationResult( err ); #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyDetachedBodyPartMemento stopped with error"; + kDebug() << "tokoe: VerifyDetachedBodyPartMemento stopped with error"; #endif - return false; - } - setRunning( true ); - return true; + return false; + } + setRunning( true ); + return true; } void VerifyDetachedBodyPartMemento::exec() { - assert( m_job ); - setRunning( true ); + assert( m_job ); + setRunning( true ); #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyDetachedBodyPartMemento execed"; + kDebug() << "tokoe: VerifyDetachedBodyPartMemento execed"; #endif - saveResult( m_job->exec( m_signature, m_plainText ) ); - m_job->deleteLater(); // exec'ed jobs don't delete themselves - m_job = 0; -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyDetachedBodyPartMemento after execed"; -#endif - if ( canStartKeyListJob() ) { - std::vector keys; - m_keylistjob->exec( keyListPattern(), /*secretOnly=*/false, keys ); - if ( !keys.empty() ) - m_key = keys.back(); - } - if ( m_keylistjob ) - m_keylistjob->deleteLater(); // exec'ed jobs don't delete themselves - m_keylistjob = 0; - setRunning( false ); + saveResult( m_job->exec( m_signature, m_plainText ) ); + m_job->deleteLater(); // exec'ed jobs don't delete themselves + m_job = 0; +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: VerifyDetachedBodyPartMemento after execed"; +#endif + if ( canStartKeyListJob() ) { + std::vector keys; + m_keylistjob->exec( keyListPattern(), /*secretOnly=*/false, keys ); + if ( !keys.empty() ) + m_key = keys.back(); + } + if ( m_keylistjob ) + m_keylistjob->deleteLater(); // exec'ed jobs don't delete themselves + m_keylistjob = 0; + setRunning( false ); } bool VerifyDetachedBodyPartMemento::canStartKeyListJob() const { - if ( !m_keylistjob ) - return false; - const char * const fpr = m_vr.signature( 0 ).fingerprint(); - return fpr && *fpr; + if ( !m_keylistjob ) + return false; + const char * const fpr = m_vr.signature( 0 ).fingerprint(); + return fpr && *fpr; } QStringList VerifyDetachedBodyPartMemento::keyListPattern() const { - assert( canStartKeyListJob() ); - return QStringList( QString::fromLatin1( m_vr.signature( 0 ).fingerprint() ) ); + assert( canStartKeyListJob() ); + return QStringList( QString::fromLatin1( m_vr.signature( 0 ).fingerprint() ) ); } void VerifyDetachedBodyPartMemento::saveResult( const VerificationResult & vr ) { - assert( m_job ); + assert( m_job ); #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyDetachedBodyPartMemento::saveResult called"; + kDebug() << "tokoe: VerifyDetachedBodyPartMemento::saveResult called"; #endif - m_vr = vr; - setAuditLog( m_job->auditLogError(), m_job->auditLogAsHtml() ); + m_vr = vr; + setAuditLog( m_job->auditLogError(), m_job->auditLogAsHtml() ); } void VerifyDetachedBodyPartMemento::slotResult( const VerificationResult & vr ) { #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyDetachedBodyPartMemento::slotResult called"; + kDebug() << "tokoe: VerifyDetachedBodyPartMemento::slotResult called"; #endif - saveResult( vr ); - m_job = 0; - if ( canStartKeyListJob() && startKeyListJob() ) { -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyDetachedBodyPartMemento: canStartKeyListJob && startKeyListJob"; -#endif - return; - } - if ( m_keylistjob ) - m_keylistjob->deleteLater(); - m_keylistjob = 0; - setRunning( false ); - notify(); + saveResult( vr ); + m_job = 0; + if ( canStartKeyListJob() && startKeyListJob() ) { +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: VerifyDetachedBodyPartMemento: canStartKeyListJob && startKeyListJob"; +#endif + return; + } + if ( m_keylistjob ) + m_keylistjob->deleteLater(); + m_keylistjob = 0; + setRunning( false ); + notify(); } bool VerifyDetachedBodyPartMemento::startKeyListJob() { - assert( canStartKeyListJob() ); - if ( const GpgME::Error err = m_keylistjob->start( keyListPattern() ) ) - return false; - connect( m_keylistjob, SIGNAL(done()), this, SLOT(slotKeyListJobDone()) ); - connect( m_keylistjob, SIGNAL(nextKey(GpgME::Key)), - this, SLOT(slotNextKey(GpgME::Key)) ); - return true; + assert( canStartKeyListJob() ); + if ( const GpgME::Error err = m_keylistjob->start( keyListPattern() ) ) + return false; + connect( m_keylistjob, SIGNAL(done()), this, SLOT(slotKeyListJobDone()) ); + connect( m_keylistjob, SIGNAL(nextKey(GpgME::Key)), + this, SLOT(slotNextKey(GpgME::Key)) ); + return true; } void VerifyDetachedBodyPartMemento::slotNextKey( const GpgME::Key & key ) { #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyDetachedBodyPartMemento::slotNextKey called"; + kDebug() << "tokoe: VerifyDetachedBodyPartMemento::slotNextKey called"; #endif - m_key = key; + m_key = key; } void VerifyDetachedBodyPartMemento::slotKeyListJobDone() { #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyDetachedBodyPartMemento::slotKeyListJobDone called"; + kDebug() << "tokoe: VerifyDetachedBodyPartMemento::slotKeyListJobDone called"; #endif - m_keylistjob = 0; - setRunning( false ); - notify(); + m_keylistjob = 0; + setRunning( false ); + notify(); } VerifyOpaqueBodyPartMemento::VerifyOpaqueBodyPartMemento( VerifyOpaqueJob * job, KeyListJob * klj, const QByteArray & signature ) - : CryptoBodyPartMemento(), - m_signature( signature ), - m_job( job ), - m_keylistjob( klj ) + : CryptoBodyPartMemento(), + m_signature( signature ), + m_job( job ), + m_keylistjob( klj ) { - assert( m_job ); + assert( m_job ); } VerifyOpaqueBodyPartMemento::~VerifyOpaqueBodyPartMemento() { - if ( m_job ) - m_job->slotCancel(); - if ( m_keylistjob ) - m_keylistjob->slotCancel(); + if ( m_job ) + m_job->slotCancel(); + if ( m_keylistjob ) + m_keylistjob->slotCancel(); } bool VerifyOpaqueBodyPartMemento::start() { - assert( m_job ); + assert( m_job ); #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyOpaqueBodyPartMemento started"; + kDebug() << "tokoe: VerifyOpaqueBodyPartMemento started"; #endif - if ( const Error err = m_job->start( m_signature ) ) { - m_vr = VerificationResult( err ); + if ( const Error err = m_job->start( m_signature ) ) { + m_vr = VerificationResult( err ); #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyOpaqueBodyPartMemento stopped with error"; + kDebug() << "tokoe: VerifyOpaqueBodyPartMemento stopped with error"; #endif - return false; - } - connect( m_job, SIGNAL(result(GpgME::VerificationResult,QByteArray)), - this, SLOT(slotResult(GpgME::VerificationResult,QByteArray)) ); - setRunning( true ); - return true; + return false; + } + connect( m_job, SIGNAL(result(GpgME::VerificationResult,QByteArray)), + this, SLOT(slotResult(GpgME::VerificationResult,QByteArray)) ); + setRunning( true ); + return true; } void VerifyOpaqueBodyPartMemento::exec() { - assert( m_job ); - setRunning( true ); - QByteArray plainText; -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyOpaqueBodyPartMemento execed"; -#endif - saveResult( m_job->exec( m_signature, plainText ), plainText ); -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyOpaqueBodyPartMemento after execed"; -#endif - m_job->deleteLater(); // exec'ed jobs don't delete themselves - m_job = 0; - if ( canStartKeyListJob() ) { - std::vector keys; - m_keylistjob->exec( keyListPattern(), /*secretOnly=*/false, keys ); - if ( !keys.empty() ) - m_key = keys.back(); - } - if ( m_keylistjob ) - m_keylistjob->deleteLater(); // exec'ed jobs don't delete themselves - m_keylistjob = 0; - setRunning( false ); + assert( m_job ); + setRunning( true ); + QByteArray plainText; +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: VerifyOpaqueBodyPartMemento execed"; +#endif + saveResult( m_job->exec( m_signature, plainText ), plainText ); +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: VerifyOpaqueBodyPartMemento after execed"; +#endif + m_job->deleteLater(); // exec'ed jobs don't delete themselves + m_job = 0; + if ( canStartKeyListJob() ) { + std::vector keys; + m_keylistjob->exec( keyListPattern(), /*secretOnly=*/false, keys ); + if ( !keys.empty() ) + m_key = keys.back(); + } + if ( m_keylistjob ) + m_keylistjob->deleteLater(); // exec'ed jobs don't delete themselves + m_keylistjob = 0; + setRunning( false ); } bool VerifyOpaqueBodyPartMemento::canStartKeyListJob() const { - if ( !m_keylistjob ) - return false; - const char * const fpr = m_vr.signature( 0 ).fingerprint(); - return fpr && *fpr; + if ( !m_keylistjob ) + return false; + const char * const fpr = m_vr.signature( 0 ).fingerprint(); + return fpr && *fpr; } QStringList VerifyOpaqueBodyPartMemento::keyListPattern() const { - assert( canStartKeyListJob() ); - return QStringList( QString::fromLatin1( m_vr.signature( 0 ).fingerprint() ) ); + assert( canStartKeyListJob() ); + return QStringList( QString::fromLatin1( m_vr.signature( 0 ).fingerprint() ) ); } void VerifyOpaqueBodyPartMemento::saveResult( const VerificationResult & vr, const QByteArray & plainText ) { - assert( m_job ); + assert( m_job ); #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyOpaqueBodyPartMemento::saveResult called"; + kDebug() << "tokoe: VerifyOpaqueBodyPartMemento::saveResult called"; #endif - m_vr = vr; - m_plainText = plainText; - setAuditLog( m_job->auditLogError(), m_job->auditLogAsHtml() ); + m_vr = vr; + m_plainText = plainText; + setAuditLog( m_job->auditLogError(), m_job->auditLogAsHtml() ); } void VerifyOpaqueBodyPartMemento::slotResult( const VerificationResult & vr, const QByteArray & plainText ) { #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyOpaqueBodyPartMemento::slotResult called"; + kDebug() << "tokoe: VerifyOpaqueBodyPartMemento::slotResult called"; #endif - saveResult( vr, plainText ); - m_job = 0; - if ( canStartKeyListJob() && startKeyListJob() ) { -#ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyOpaqueBodyPartMemento: canStartKeyListJob && startKeyListJob"; -#endif - return; - } - if ( m_keylistjob ) - m_keylistjob->deleteLater(); - m_keylistjob = 0; - setRunning( false ); - notify(); + saveResult( vr, plainText ); + m_job = 0; + if ( canStartKeyListJob() && startKeyListJob() ) { +#ifdef DEBUG_SIGNATURE + kDebug() << "tokoe: VerifyOpaqueBodyPartMemento: canStartKeyListJob && startKeyListJob"; +#endif + return; + } + if ( m_keylistjob ) + m_keylistjob->deleteLater(); + m_keylistjob = 0; + setRunning( false ); + notify(); } bool VerifyOpaqueBodyPartMemento::startKeyListJob() { - assert( canStartKeyListJob() ); - if ( const GpgME::Error err = m_keylistjob->start( keyListPattern() ) ) - return false; - connect( m_keylistjob, SIGNAL(done()), this, SLOT(slotKeyListJobDone()) ); - connect( m_keylistjob, SIGNAL(nextKey(GpgME::Key)), - this, SLOT(slotNextKey(GpgME::Key)) ); - return true; + assert( canStartKeyListJob() ); + if ( const GpgME::Error err = m_keylistjob->start( keyListPattern() ) ) + return false; + connect( m_keylistjob, SIGNAL(done()), this, SLOT(slotKeyListJobDone()) ); + connect( m_keylistjob, SIGNAL(nextKey(GpgME::Key)), + this, SLOT(slotNextKey(GpgME::Key)) ); + return true; } void VerifyOpaqueBodyPartMemento::slotNextKey( const GpgME::Key & key ) { #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyOpaqueBodyPartMemento::slotNextKey called"; + kDebug() << "tokoe: VerifyOpaqueBodyPartMemento::slotNextKey called"; #endif - m_key = key; + m_key = key; } void VerifyOpaqueBodyPartMemento::slotKeyListJobDone() { #ifdef DEBUG_SIGNATURE - kDebug() << "tokoe: VerifyOpaqueBodyPartMemento::slotKeyListJobDone called"; + kDebug() << "tokoe: VerifyOpaqueBodyPartMemento::slotKeyListJobDone called"; #endif - m_keylistjob = 0; - setRunning( false ); - notify(); + m_keylistjob = 0; + setRunning( false ); + notify(); } diff -Nru kdepim-4.12.97/messageviewer/viewer/objecttreeparser_p.h kdepim-4.13.0/messageviewer/viewer/objecttreeparser_p.h --- kdepim-4.12.97/messageviewer/viewer/objecttreeparser_p.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/objecttreeparser_p.h 2014-04-10 07:40:20.000000000 +0000 @@ -45,10 +45,10 @@ #include "viewer/viewer.h" namespace Kleo { - class DecryptVerifyJob; - class VerifyDetachedJob; - class VerifyOpaqueJob; - class KeyListJob; +class DecryptVerifyJob; +class VerifyDetachedJob; +class VerifyOpaqueJob; +class KeyListJob; } class QStringList; @@ -56,151 +56,151 @@ namespace MessageViewer { class CryptoBodyPartMemento - : public QObject, - public Interface::BodyPartMemento + : public QObject, + public Interface::BodyPartMemento { - Q_OBJECT + Q_OBJECT public: - CryptoBodyPartMemento(); - ~CryptoBodyPartMemento(); + CryptoBodyPartMemento(); + ~CryptoBodyPartMemento(); - bool isRunning() const { return m_running; } + bool isRunning() const { return m_running; } - const QString & auditLogAsHtml() const { return m_auditLog; } - GpgME::Error auditLogError() const { return m_auditLogError; } + const QString & auditLogAsHtml() const { return m_auditLog; } + GpgME::Error auditLogError() const { return m_auditLogError; } - void detach(); + void detach(); signals: - void update(MessageViewer::Viewer::UpdateMode); + void update(MessageViewer::Viewer::UpdateMode); protected slots: - void notify() { - emit update(Viewer::Force); - } + void notify() { + emit update(Viewer::Force); + } protected: - void setAuditLog( const GpgME::Error & err, const QString & log ); - void setRunning( bool running ); + void setAuditLog( const GpgME::Error & err, const QString & log ); + void setRunning( bool running ); private: - bool m_running; - QString m_auditLog; - GpgME::Error m_auditLogError; + bool m_running; + QString m_auditLog; + GpgME::Error m_auditLogError; }; class DecryptVerifyBodyPartMemento - : public CryptoBodyPartMemento + : public CryptoBodyPartMemento { - Q_OBJECT + Q_OBJECT public: - DecryptVerifyBodyPartMemento( Kleo::DecryptVerifyJob * job, const QByteArray & cipherText ); - ~DecryptVerifyBodyPartMemento(); + DecryptVerifyBodyPartMemento( Kleo::DecryptVerifyJob * job, const QByteArray & cipherText ); + ~DecryptVerifyBodyPartMemento(); - bool start(); - void exec(); + bool start(); + void exec(); - const QByteArray & plainText() const { return m_plainText; } - const GpgME::DecryptionResult & decryptResult() const { return m_dr; } - const GpgME::VerificationResult & verifyResult() const { return m_vr; } + const QByteArray & plainText() const { return m_plainText; } + const GpgME::DecryptionResult & decryptResult() const { return m_dr; } + const GpgME::VerificationResult & verifyResult() const { return m_vr; } private slots: - void slotResult( const GpgME::DecryptionResult & dr, - const GpgME::VerificationResult & vr, - const QByteArray & plainText ); - -private: - void saveResult( const GpgME::DecryptionResult &, - const GpgME::VerificationResult &, - const QByteArray & ); -private: - // input: - const QByteArray m_cipherText; - QPointer m_job; - // output: - GpgME::DecryptionResult m_dr; - GpgME::VerificationResult m_vr; - QByteArray m_plainText; + void slotResult( const GpgME::DecryptionResult & dr, + const GpgME::VerificationResult & vr, + const QByteArray & plainText ); + +private: + void saveResult( const GpgME::DecryptionResult &, + const GpgME::VerificationResult &, + const QByteArray & ); +private: + // input: + const QByteArray m_cipherText; + QPointer m_job; + // output: + GpgME::DecryptionResult m_dr; + GpgME::VerificationResult m_vr; + QByteArray m_plainText; }; class VerifyDetachedBodyPartMemento - : public CryptoBodyPartMemento + : public CryptoBodyPartMemento { - Q_OBJECT + Q_OBJECT public: - VerifyDetachedBodyPartMemento( Kleo::VerifyDetachedJob * job, - Kleo::KeyListJob * klj, - const QByteArray & signature, - const QByteArray & plainText ); - ~VerifyDetachedBodyPartMemento(); + VerifyDetachedBodyPartMemento( Kleo::VerifyDetachedJob * job, + Kleo::KeyListJob * klj, + const QByteArray & signature, + const QByteArray & plainText ); + ~VerifyDetachedBodyPartMemento(); - bool start(); - void exec(); + bool start(); + void exec(); - const GpgME::VerificationResult & verifyResult() const { return m_vr; } - const GpgME::Key & signingKey() const { return m_key; } + const GpgME::VerificationResult & verifyResult() const { return m_vr; } + const GpgME::Key & signingKey() const { return m_key; } private slots: - void slotResult( const GpgME::VerificationResult & vr ); - void slotKeyListJobDone(); - void slotNextKey( const GpgME::Key & ); - -private: - void saveResult( const GpgME::VerificationResult & ); - bool canStartKeyListJob() const; - QStringList keyListPattern() const; - bool startKeyListJob(); -private: - // input: - const QByteArray m_signature; - const QByteArray m_plainText; - QPointer m_job; - QPointer m_keylistjob; - // output: - GpgME::VerificationResult m_vr; - GpgME::Key m_key; + void slotResult( const GpgME::VerificationResult & vr ); + void slotKeyListJobDone(); + void slotNextKey( const GpgME::Key & ); + +private: + void saveResult( const GpgME::VerificationResult & ); + bool canStartKeyListJob() const; + QStringList keyListPattern() const; + bool startKeyListJob(); +private: + // input: + const QByteArray m_signature; + const QByteArray m_plainText; + QPointer m_job; + QPointer m_keylistjob; + // output: + GpgME::VerificationResult m_vr; + GpgME::Key m_key; }; class VerifyOpaqueBodyPartMemento - : public CryptoBodyPartMemento + : public CryptoBodyPartMemento { - Q_OBJECT + Q_OBJECT public: - VerifyOpaqueBodyPartMemento( Kleo::VerifyOpaqueJob * job, - Kleo::KeyListJob * klj, - const QByteArray & signature ); - ~VerifyOpaqueBodyPartMemento(); - - bool start(); - void exec(); - - const QByteArray & plainText() const { return m_plainText; } - const GpgME::VerificationResult & verifyResult() const { return m_vr; } - const GpgME::Key & signingKey() const { return m_key; } + VerifyOpaqueBodyPartMemento( Kleo::VerifyOpaqueJob * job, + Kleo::KeyListJob * klj, + const QByteArray & signature ); + ~VerifyOpaqueBodyPartMemento(); + + bool start(); + void exec(); + + const QByteArray & plainText() const { return m_plainText; } + const GpgME::VerificationResult & verifyResult() const { return m_vr; } + const GpgME::Key & signingKey() const { return m_key; } private slots: - void slotResult( const GpgME::VerificationResult & vr, - const QByteArray & plainText ); - void slotKeyListJobDone(); - void slotNextKey( const GpgME::Key & ); - -private: - void saveResult( const GpgME::VerificationResult &, - const QByteArray & ); - bool canStartKeyListJob() const; - QStringList keyListPattern() const; - bool startKeyListJob(); -private: - // input: - const QByteArray m_signature; - QPointer m_job; - QPointer m_keylistjob; - // output: - GpgME::VerificationResult m_vr; - QByteArray m_plainText; - GpgME::Key m_key; + void slotResult( const GpgME::VerificationResult & vr, + const QByteArray & plainText ); + void slotKeyListJobDone(); + void slotNextKey( const GpgME::Key & ); + +private: + void saveResult( const GpgME::VerificationResult &, + const QByteArray & ); + bool canStartKeyListJob() const; + QStringList keyListPattern() const; + bool startKeyListJob(); +private: + // input: + const QByteArray m_signature; + QPointer m_job; + QPointer m_keylistjob; + // output: + GpgME::VerificationResult m_vr; + QByteArray m_plainText; + GpgME::Key m_key; }; } diff -Nru kdepim-4.12.97/messageviewer/viewer/objecttreeviewersource.cpp kdepim-4.13.0/messageviewer/viewer/objecttreeviewersource.cpp --- kdepim-4.12.97/messageviewer/viewer/objecttreeviewersource.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/objecttreeviewersource.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -25,7 +25,7 @@ namespace MessageViewer { MailViewerSource::MailViewerSource( ViewerPrivate *viewer ) : - ObjectTreeSourceIf(), mViewer( viewer ) + ObjectTreeSourceIf(), mViewer( viewer ) { } @@ -35,62 +35,62 @@ bool MailViewerSource::htmlMail() { - return mViewer->htmlMail(); + return mViewer->htmlMail(); } bool MailViewerSource::decryptMessage() { - return mViewer->decryptMessage(); + return mViewer->decryptMessage(); } bool MailViewerSource::htmlLoadExternal() { - return mViewer->htmlLoadExternal(); + return mViewer->htmlLoadExternal(); } bool MailViewerSource::showSignatureDetails() { - return mViewer->mShowSignatureDetails; + return mViewer->mShowSignatureDetails; } void MailViewerSource::setHtmlMode( Util::HtmlMode mode ) { - mViewer->mColorBar->setMode( mode ); + mViewer->mColorBar->setMode( mode ); } int MailViewerSource::levelQuote() { - return mViewer->mLevelQuote; + return mViewer->mLevelQuote; } const QTextCodec * MailViewerSource::overrideCodec() { - return mViewer->overrideCodec(); + return mViewer->overrideCodec(); } QString MailViewerSource::createMessageHeader( KMime::Message *message ) { - return mViewer->writeMsgHeader( message ); + return mViewer->writeMsgHeader( message ); } QObject *MailViewerSource::sourceObject() { - return mViewer; + return mViewer; } const AttachmentStrategy * MailViewerSource::attachmentStrategy() { - return mViewer->attachmentStrategy(); + return mViewer->attachmentStrategy(); } HtmlWriter * MailViewerSource::htmlWriter() { - return mViewer->htmlWriter(); + return mViewer->htmlWriter(); } CSSHelper* MailViewerSource::cssHelper() { - return mViewer->cssHelper(); + return mViewer->cssHelper(); } } diff -Nru kdepim-4.12.97/messageviewer/viewer/objecttreeviewersource.h kdepim-4.13.0/messageviewer/viewer/objecttreeviewersource.h --- kdepim-4.12.97/messageviewer/viewer/objecttreeviewersource.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/objecttreeviewersource.h 2014-04-10 07:40:20.000000000 +0000 @@ -25,28 +25,28 @@ class QString; namespace MessageViewer { - + class ViewerPrivate; /** An ObjectTreeParser source working on a MailViewer object */ class MailViewerSource : public ObjectTreeSourceIf { - public: - explicit MailViewerSource( ViewerPrivate * viewer); - ~MailViewerSource(); - bool htmlMail(); - bool decryptMessage(); - bool htmlLoadExternal(); - bool showSignatureDetails(); - void setHtmlMode( Util::HtmlMode mode ); - int levelQuote(); - const QTextCodec * overrideCodec(); - QString createMessageHeader( KMime::Message *message ); - const AttachmentStrategy * attachmentStrategy(); - HtmlWriter * htmlWriter(); - CSSHelper* cssHelper(); - QObject *sourceObject(); +public: + explicit MailViewerSource( ViewerPrivate * viewer); + ~MailViewerSource(); + bool htmlMail(); + bool decryptMessage(); + bool htmlLoadExternal(); + bool showSignatureDetails(); + void setHtmlMode( Util::HtmlMode mode ); + int levelQuote(); + const QTextCodec * overrideCodec(); + QString createMessageHeader( KMime::Message *message ); + const AttachmentStrategy * attachmentStrategy(); + HtmlWriter * htmlWriter(); + CSSHelper* cssHelper(); + QObject *sourceObject(); - private: +private: ViewerPrivate *mViewer; }; diff -Nru kdepim-4.12.97/messageviewer/viewer/partnodebodypart.cpp kdepim-4.13.0/messageviewer/viewer/partnodebodypart.cpp --- kdepim-4.12.97/messageviewer/viewer/partnodebodypart.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/partnodebodypart.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -51,61 +51,61 @@ PartNodeBodyPart::PartNodeBodyPart( KMime::Content *topLevelContent, KMime::Content *content, NodeHelper *nodeHelper, const QTextCodec * codec ) - : Interface::BodyPart(), mTopLevelContent( topLevelContent ), mContent( content ), mCodec( codec ), - mDefaultDisplay( Interface::BodyPart::None ), mNodeHelper( nodeHelper ) + : Interface::BodyPart(), mTopLevelContent( topLevelContent ), mContent( content ), mCodec( codec ), + mDefaultDisplay( Interface::BodyPart::None ), mNodeHelper( nodeHelper ) {} QString PartNodeBodyPart::makeLink( const QString & path ) const { - // FIXME: use a PRNG for the first arg, instead of a serial number - return QString::fromLatin1( "x-kmail:/bodypart/%1/%2/%3" ) - .arg( serial++ ).arg( mContent->index().toString() ) - .arg( QString::fromLatin1( KUrl::toPercentEncoding( path, "/" ) ) ); + // FIXME: use a PRNG for the first arg, instead of a serial number + return QString::fromLatin1( "x-kmail:/bodypart/%1/%2/%3" ) + .arg( serial++ ).arg( mContent->index().toString() ) + .arg( QString::fromLatin1( KUrl::toPercentEncoding( path, "/" ) ) ); } QString PartNodeBodyPart::asText() const { - if ( !mContent->contentType()->isText() ) - return QString(); - return mContent->decodedText(); + if ( !mContent->contentType()->isText() ) + return QString(); + return mContent->decodedText(); } QByteArray PartNodeBodyPart::asBinary() const { - return mContent->decodedContent(); + return mContent->decodedContent(); } QString PartNodeBodyPart::contentTypeParameter( const char * param ) const { - return mContent->contentType()->parameter( QString::fromLatin1(param) ); + return mContent->contentType()->parameter( QString::fromLatin1(param) ); } QString PartNodeBodyPart::contentDescription() const { - return mContent->contentDescription()->asUnicodeString(); + return mContent->contentDescription()->asUnicodeString(); } QString PartNodeBodyPart::contentDispositionParameter( const char * param ) const { - return mContent->contentDisposition()->parameter( QString::fromLatin1(param) ); + return mContent->contentDisposition()->parameter( QString::fromLatin1(param) ); } bool PartNodeBodyPart::hasCompleteBody() const { - kWarning() << "Sorry, not yet implemented."; - return true; + kWarning() << "Sorry, not yet implemented."; + return true; } Interface::BodyPartMemento * PartNodeBodyPart::memento() const { - /*TODO(Andras) Volker suggests to use a ContentIndex->Mememnto mapping + /*TODO(Andras) Volker suggests to use a ContentIndex->Mememnto mapping Also review if the reader's bodyPartMemento should be returned or the NodeHelper's one */ - return mNodeHelper->bodyPartMemento( mContent, "__plugin__" ); + return mNodeHelper->bodyPartMemento( mContent, "__plugin__" ); } void PartNodeBodyPart::setBodyPartMemento( Interface::BodyPartMemento * memento ) { -/*TODO(Andras) Volker suggests to use a ContentIndex->Memento mapping + /*TODO(Andras) Volker suggests to use a ContentIndex->Memento mapping Also review if the reader's bodyPartMemento should be set or the NodeHelper's one */ - mNodeHelper->setBodyPartMemento( mContent, "__plugin__" , memento ); + mNodeHelper->setBodyPartMemento( mContent, "__plugin__" , memento ); } Interface::BodyPart::Display PartNodeBodyPart::defaultDisplay() const { - return mDefaultDisplay; + return mDefaultDisplay; } void PartNodeBodyPart::setDefaultDisplay( Interface::BodyPart::Display d ){ - mDefaultDisplay = d; + mDefaultDisplay = d; } diff -Nru kdepim-4.12.97/messageviewer/viewer/partnodebodypart.h kdepim-4.13.0/messageviewer/viewer/partnodebodypart.h --- kdepim-4.12.97/messageviewer/viewer/partnodebodypart.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/partnodebodypart.h 2014-04-10 07:40:20.000000000 +0000 @@ -40,11 +40,11 @@ class QTextCodec; namespace KMime { - class Content; +class Content; } namespace MessageViewer { - class NodeHelper; +class NodeHelper; } namespace MessageViewer { @@ -54,32 +54,32 @@ */ class PartNodeBodyPart : public Interface::BodyPart { public: - explicit PartNodeBodyPart( KMime::Content *topLevelContent, KMime::Content* content, - NodeHelper *nodeHelper, const QTextCodec * codec=0 ); + explicit PartNodeBodyPart( KMime::Content *topLevelContent, KMime::Content* content, + NodeHelper *nodeHelper, const QTextCodec * codec=0 ); - QString makeLink( const QString & path ) const; - QString asText() const; - QByteArray asBinary() const; - QString contentTypeParameter( const char * param ) const; - QString contentDescription() const; - //int contentDisposition() const; - QString contentDispositionParameter( const char * param ) const; - bool hasCompleteBody() const; - - Interface::BodyPartMemento * memento() const; - void setBodyPartMemento( Interface::BodyPartMemento * memento ); - BodyPart::Display defaultDisplay() const; - void setDefaultDisplay( BodyPart::Display ); - KMime::Content* content() const { return mContent; } - KMime::Content* topLevelContent() const { return mTopLevelContent; } - NodeHelper* nodeHelper() const { return mNodeHelper; } + QString makeLink( const QString & path ) const; + QString asText() const; + QByteArray asBinary() const; + QString contentTypeParameter( const char * param ) const; + QString contentDescription() const; + //int contentDisposition() const; + QString contentDispositionParameter( const char * param ) const; + bool hasCompleteBody() const; + + Interface::BodyPartMemento * memento() const; + void setBodyPartMemento( Interface::BodyPartMemento * memento ); + BodyPart::Display defaultDisplay() const; + void setDefaultDisplay( BodyPart::Display ); + KMime::Content* content() const { return mContent; } + KMime::Content* topLevelContent() const { return mTopLevelContent; } + NodeHelper* nodeHelper() const { return mNodeHelper; } private: - KMime::Content *mTopLevelContent; - KMime::Content *mContent; - const QTextCodec * mCodec; - BodyPart::Display mDefaultDisplay; - NodeHelper *mNodeHelper; + KMime::Content *mTopLevelContent; + KMime::Content *mContent; + const QTextCodec * mCodec; + BodyPart::Display mDefaultDisplay; + NodeHelper *mNodeHelper; }; } diff -Nru kdepim-4.12.97/messageviewer/viewer/pluginloaderbase.cpp kdepim-4.13.0/messageviewer/viewer/pluginloaderbase.cpp --- kdepim-4.12.97/messageviewer/viewer/pluginloaderbase.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/pluginloaderbase.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -38,96 +38,96 @@ PluginLoaderBase::~PluginLoaderBase() {} QStringList PluginLoaderBase::types() const { - QStringList result; - QMap< QString, PluginMetaData >::const_iterator end( mPluginMap.constEnd() ); - for ( QMap< QString, PluginMetaData >::const_iterator it = mPluginMap.constBegin(); it != end ; ++it ) - result.push_back( it.key() ); - return result; + QStringList result; + QMap< QString, PluginMetaData >::const_iterator end( mPluginMap.constEnd() ); + for ( QMap< QString, PluginMetaData >::const_iterator it = mPluginMap.constBegin(); it != end ; ++it ) + result.push_back( it.key() ); + return result; } const PluginMetaData * PluginLoaderBase::infoForName( const QString & type ) const { - return mPluginMap.contains( type ) ? &(const_cast(this)->mPluginMap[type]) : 0 ; + return mPluginMap.contains( type ) ? &(const_cast(this)->mPluginMap[type]) : 0 ; } void PluginLoaderBase::doScan( const char * path ) { - mPluginMap.clear(); + mPluginMap.clear(); - const QStringList list = - KGlobal::dirs()->findAllResources( "data", QString::fromLatin1(path), - KStandardDirs::Recursive | - KStandardDirs::NoDuplicates ); - for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it ) { - KConfig config( *it, KConfig::SimpleConfig); - if ( config.hasGroup( "Misc" ) && config.hasGroup( "Plugin" ) ) { - KConfigGroup group( &config, "Plugin" ); - - const QString type = group.readEntry( "Type" ).toLower(); - if ( type.isEmpty() ) { - kWarning() << "missing or empty [Plugin]Type value in \"" << *it << "\" - skipping"; - continue; - } - - const QString library = group.readEntry( "X-KDE-Library" ); - if ( library.isEmpty() ) { - kWarning() << "missing or empty [Plugin]X-KDE-Library value in \"" << *it << "\" - skipping"; - continue; - } - - KConfigGroup group2( &config, "Misc" ); - - QString name = group2.readEntry( "Name" ); - if ( name.isEmpty() ) { - kWarning() << "missing or empty [Misc]Name value in \"" << *it << "\" - inserting default name"; - name = i18n("Unnamed plugin"); - } - - QString comment = group2.readEntry( "Comment" ); - if ( comment.isEmpty() ) { - kWarning() << "missing or empty [Misc]Comment value in \"" << *it << "\" - inserting default name"; - comment = i18n("No description available"); - } - - mPluginMap.insert( type, PluginMetaData( library, name, comment ) ); - } else { - kWarning() << "Desktop file \"" << *it << "\" doesn't seem to describe a plugin " << "(misses Misc and/or Plugin group)"; + const QStringList list = + KGlobal::dirs()->findAllResources( "data", QString::fromLatin1(path), + KStandardDirs::Recursive | + KStandardDirs::NoDuplicates ); + for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it ) { + KConfig config( *it, KConfig::SimpleConfig); + if ( config.hasGroup( "Misc" ) && config.hasGroup( "Plugin" ) ) { + KConfigGroup group( &config, "Plugin" ); + + const QString type = group.readEntry( "Type" ).toLower(); + if ( type.isEmpty() ) { + kWarning() << "missing or empty [Plugin]Type value in \"" << *it << "\" - skipping"; + continue; + } + + const QString library = group.readEntry( "X-KDE-Library" ); + if ( library.isEmpty() ) { + kWarning() << "missing or empty [Plugin]X-KDE-Library value in \"" << *it << "\" - skipping"; + continue; + } + + KConfigGroup group2( &config, "Misc" ); + + QString name = group2.readEntry( "Name" ); + if ( name.isEmpty() ) { + kWarning() << "missing or empty [Misc]Name value in \"" << *it << "\" - inserting default name"; + name = i18n("Unnamed plugin"); + } + + QString comment = group2.readEntry( "Comment" ); + if ( comment.isEmpty() ) { + kWarning() << "missing or empty [Misc]Comment value in \"" << *it << "\" - inserting default name"; + comment = i18n("No description available"); + } + + mPluginMap.insert( type, PluginMetaData( library, name, comment ) ); + } else { + kWarning() << "Desktop file \"" << *it << "\" doesn't seem to describe a plugin " << "(misses Misc and/or Plugin group)"; + } } - } } KLibrary::void_function_ptr PluginLoaderBase::mainFunc( const QString & type, const char * mf_name ) const { - if ( type.isEmpty() || !mPluginMap.contains( type ) ) - return 0; + if ( type.isEmpty() || !mPluginMap.contains( type ) ) + return 0; - const QString libName = mPluginMap[ type ].library; - if ( libName.isEmpty() ) - return 0; - - const KLibrary * lib = openLibrary( libName ); - if ( !lib ) - return 0; - - PluginMetaData pmd = mPluginMap.value( type ); - pmd.loaded = true; - mPluginMap[ type ] = pmd; - - const QString factory_name = libName + QLatin1Char('_') + QString::fromLatin1(mf_name); - KLibrary::void_function_ptr sym = const_cast( lib )->resolveFunction( factory_name.toLatin1() ); - if ( !sym ) { - kWarning() << "No symbol named \"" << factory_name.toLatin1() << "\" (" << factory_name << ") was found in library \"" << libName << "\""; - return 0; - } + const QString libName = mPluginMap[ type ].library; + if ( libName.isEmpty() ) + return 0; + + const KLibrary * lib = openLibrary( libName ); + if ( !lib ) + return 0; + + PluginMetaData pmd = mPluginMap.value( type ); + pmd.loaded = true; + mPluginMap[ type ] = pmd; + + const QString factory_name = libName + QLatin1Char('_') + QString::fromLatin1(mf_name); + KLibrary::void_function_ptr sym = const_cast( lib )->resolveFunction( factory_name.toLatin1() ); + if ( !sym ) { + kWarning() << "No symbol named \"" << factory_name.toLatin1() << "\" (" << factory_name << ") was found in library \"" << libName << "\""; + return 0; + } - return sym; + return sym; } const KLibrary * PluginLoaderBase::openLibrary( const QString & libName ) const { - KLibrary * library = new KLibrary( libName ); - if ( library->fileName().isEmpty() || !library->load() ) { - kWarning() << "Could not load plugin library" << libName << "error:" << library->errorString() << library->fileName(); - delete library; - return 0; - } + KLibrary * library = new KLibrary( libName ); + if ( library->fileName().isEmpty() || !library->load() ) { + kWarning() << "Could not load plugin library" << libName << "error:" << library->errorString() << library->fileName(); + delete library; + return 0; + } - return library; + return library; } diff -Nru kdepim-4.12.97/messageviewer/viewer/pluginloaderbase.h kdepim-4.13.0/messageviewer/viewer/pluginloaderbase.h --- kdepim-4.12.97/messageviewer/viewer/pluginloaderbase.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/pluginloaderbase.h 2014-04-10 07:40:20.000000000 +0000 @@ -30,12 +30,12 @@ class PluginMetaData { - public: +public: PluginMetaData() : loaded(false) {} PluginMetaData( const QString & lib, const QString & name, const QString & comment ) - : library( lib ), nameLabel( name ), - descriptionLabel( comment ), loaded( false ) {} + : library( lib ), nameLabel( name ), + descriptionLabel( comment ), loaded( false ) {} QString library; QString nameLabel; QString descriptionLabel; @@ -44,11 +44,11 @@ class PluginLoaderBase { - protected: +protected: PluginLoaderBase(); virtual ~PluginLoaderBase(); - public: +public: /** Returns a list of all available plugin objects (of kind @p T) */ QStringList types() const; @@ -59,7 +59,7 @@ the right @p path argument */ virtual void scan() = 0; - protected: +protected: /** Rescans the plugin directory to find any newly installed plugins. Extend this method in subclasses to add any builtins. Subclasses must call this explicitly. It's not @@ -71,7 +71,7 @@ implements the plugin of type @p type */ KLibrary::void_function_ptr mainFunc( const QString & type, const char * main_func ) const; - private: +private: const KLibrary * openLibrary( const QString & libName ) const; mutable QMap< QString, PluginMetaData > mPluginMap; diff -Nru kdepim-4.12.97/messageviewer/viewer/urlhandlermanager.cpp kdepim-4.13.0/messageviewer/viewer/urlhandlermanager.cpp --- kdepim-4.12.97/messageviewer/viewer/urlhandlermanager.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/urlhandlermanager.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -80,79 +80,79 @@ URLHandlerManager * URLHandlerManager::self = 0; namespace { - class KMailProtocolURLHandler : public URLHandler { - public: +class KMailProtocolURLHandler : public URLHandler { +public: KMailProtocolURLHandler() : URLHandler() {} ~KMailProtocolURLHandler() {} bool handleClick( const KUrl &, ViewerPrivate * ) const; bool handleContextMenuRequest( const KUrl & url, const QPoint &, ViewerPrivate * ) const { - return url.protocol() == QLatin1String( "kmail" ); + return url.protocol() == QLatin1String( "kmail" ); } QString statusBarMessage( const KUrl &, ViewerPrivate * ) const; - }; +}; - class ExpandCollapseQuoteURLManager : public URLHandler { - public: +class ExpandCollapseQuoteURLManager : public URLHandler { +public: ExpandCollapseQuoteURLManager() : URLHandler() {} ~ExpandCollapseQuoteURLManager() {} bool handleClick( const KUrl &, ViewerPrivate * ) const; bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const { - return false; + return false; } QString statusBarMessage( const KUrl &, ViewerPrivate * ) const; - }; +}; - class SMimeURLHandler : public URLHandler { - public: +class SMimeURLHandler : public URLHandler { +public: SMimeURLHandler() : URLHandler() {} ~SMimeURLHandler() {} bool handleClick( const KUrl &, ViewerPrivate * ) const; bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const { - return false; + return false; } QString statusBarMessage( const KUrl &, ViewerPrivate * ) const; - }; +}; - class MailToURLHandler : public URLHandler { - public: +class MailToURLHandler : public URLHandler { +public: MailToURLHandler() : URLHandler() {} ~MailToURLHandler() {} bool handleClick( const KUrl &, ViewerPrivate * ) const { return false; } bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const { - return false; + return false; } QString statusBarMessage( const KUrl &, ViewerPrivate * ) const; - }; +}; - class ContactUidURLHandler : public URLHandler { - public: +class ContactUidURLHandler : public URLHandler { +public: ContactUidURLHandler() : URLHandler() {} ~ContactUidURLHandler() {} bool handleClick( const KUrl &, ViewerPrivate * ) const; bool handleContextMenuRequest( const KUrl &url, const QPoint &p, ViewerPrivate * ) const; QString statusBarMessage( const KUrl &, ViewerPrivate * ) const; - }; +}; - class HtmlAnchorHandler : public URLHandler { - public: +class HtmlAnchorHandler : public URLHandler { +public: HtmlAnchorHandler() : URLHandler() {} ~HtmlAnchorHandler() {} bool handleClick( const KUrl &, ViewerPrivate * ) const; bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const { - return false; + return false; } QString statusBarMessage( const KUrl &, ViewerPrivate * ) const { return QString(); } - }; +}; - class AttachmentURLHandler : public URLHandler { - public: +class AttachmentURLHandler : public URLHandler { +public: AttachmentURLHandler() : URLHandler() {} ~AttachmentURLHandler() {} @@ -162,52 +162,52 @@ bool handleDrag( const KUrl &url, ViewerPrivate *window ) const; bool willHandleDrag( const KUrl &url, ViewerPrivate *window ) const; QString statusBarMessage( const KUrl &, ViewerPrivate * ) const; - private: +private: KMime::Content* nodeForUrl( const KUrl &url, ViewerPrivate *w ) const; bool attachmentIsInHeader( const KUrl &url ) const; - }; +}; - class ShowAuditLogURLHandler : public URLHandler { - public: - ShowAuditLogURLHandler() : URLHandler() {} - ~ShowAuditLogURLHandler() {} - - bool handleClick( const KUrl &, ViewerPrivate * ) const; - bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const; - QString statusBarMessage( const KUrl &, ViewerPrivate * ) const; - }; - - // Handler that prevents dragging of internal images added by KMail, such as the envelope image - // in the enterprise header - class InternalImageURLHandler : public URLHandler { - public: - InternalImageURLHandler() : URLHandler() - {} - ~InternalImageURLHandler() - {} - bool handleDrag( const KUrl &url, ViewerPrivate *window ) const; - bool willHandleDrag( const KUrl &url, ViewerPrivate *window ) const; - bool handleClick( const KUrl &, ViewerPrivate * ) const - { return false; } - bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const - { return false; } - QString statusBarMessage( const KUrl &, ViewerPrivate * ) const - { return QString(); } - }; - - class KRunURLHandler : public URLHandler { - public: - KRunURLHandler() : URLHandler() - {} - ~KRunURLHandler() - {} - - bool handleClick( const KUrl &, ViewerPrivate * ) const; - bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const { - return false; - } - QString statusBarMessage( const KUrl &, ViewerPrivate * ) const { return QString(); } - }; +class ShowAuditLogURLHandler : public URLHandler { +public: + ShowAuditLogURLHandler() : URLHandler() {} + ~ShowAuditLogURLHandler() {} + + bool handleClick( const KUrl &, ViewerPrivate * ) const; + bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const; + QString statusBarMessage( const KUrl &, ViewerPrivate * ) const; +}; + +// Handler that prevents dragging of internal images added by KMail, such as the envelope image +// in the enterprise header +class InternalImageURLHandler : public URLHandler { +public: + InternalImageURLHandler() : URLHandler() + {} + ~InternalImageURLHandler() + {} + bool handleDrag( const KUrl &url, ViewerPrivate *window ) const; + bool willHandleDrag( const KUrl &url, ViewerPrivate *window ) const; + bool handleClick( const KUrl &, ViewerPrivate * ) const + { return false; } + bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const + { return false; } + QString statusBarMessage( const KUrl &, ViewerPrivate * ) const + { return QString(); } +}; + +class KRunURLHandler : public URLHandler { +public: + KRunURLHandler() : URLHandler() + {} + ~KRunURLHandler() + {} + + bool handleClick( const KUrl &, ViewerPrivate * ) const; + bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const { + return false; + } + QString statusBarMessage( const KUrl &, ViewerPrivate * ) const { return QString(); } +}; } // anon namespace @@ -220,104 +220,104 @@ class URLHandlerManager::BodyPartURLHandlerManager : public URLHandler { public: - BodyPartURLHandlerManager() : URLHandler() {} - ~BodyPartURLHandlerManager(); + BodyPartURLHandlerManager() : URLHandler() {} + ~BodyPartURLHandlerManager(); - bool handleClick( const KUrl &, ViewerPrivate * ) const; - bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const; - QString statusBarMessage( const KUrl &, ViewerPrivate * ) const; + bool handleClick( const KUrl &, ViewerPrivate * ) const; + bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const; + QString statusBarMessage( const KUrl &, ViewerPrivate * ) const; - void registerHandler( const Interface::BodyPartURLHandler * handler ); - void unregisterHandler( const Interface::BodyPartURLHandler * handler ); + void registerHandler( const Interface::BodyPartURLHandler * handler ); + void unregisterHandler( const Interface::BodyPartURLHandler * handler ); private: - typedef QVector BodyPartHandlerList; - BodyPartHandlerList mHandlers; + typedef QVector BodyPartHandlerList; + BodyPartHandlerList mHandlers; }; URLHandlerManager::BodyPartURLHandlerManager::~BodyPartURLHandlerManager() { - for_each( mHandlers.begin(), mHandlers.end(), - DeleteAndSetToZero() ); + for_each( mHandlers.begin(), mHandlers.end(), + DeleteAndSetToZero() ); } void URLHandlerManager::BodyPartURLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) { - if ( !handler ) - return; - unregisterHandler( handler ); // don't produce duplicates - mHandlers.push_back( handler ); + if ( !handler ) + return; + unregisterHandler( handler ); // don't produce duplicates + mHandlers.push_back( handler ); } void URLHandlerManager::BodyPartURLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) { - // don't delete them, only remove them from the list! - mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() ); + // don't delete them, only remove them from the list! + mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() ); } static KMime::Content * partNodeFromXKMailUrl( const KUrl & url, ViewerPrivate * w, QString * path ) { - assert( path ); - - if ( !w || url.protocol() != QLatin1String( "x-kmail" ) ) - return 0; - const QString urlPath = url.path(); - - // urlPath format is: /bodypart/// + assert( path ); - kDebug() << "BodyPartURLHandler: urlPath ==" << urlPath; - if ( !urlPath.startsWith( QLatin1String("/bodypart/") ) ) - return 0; - - const QStringList urlParts = urlPath.mid( 10 ).split( QLatin1Char('/') ); - if ( urlParts.size() != 3 ) - return 0; - //KMime::ContentIndex index( urlParts[1] ); - *path = KUrl::fromPercentEncoding( urlParts[2].toLatin1() ); - return w->nodeFromUrl( urlParts[1] ); + if ( !w || url.protocol() != QLatin1String( "x-kmail" ) ) + return 0; + const QString urlPath = url.path(); + + // urlPath format is: /bodypart/// + + kDebug() << "BodyPartURLHandler: urlPath ==" << urlPath; + if ( !urlPath.startsWith( QLatin1String("/bodypart/") ) ) + return 0; + + const QStringList urlParts = urlPath.mid( 10 ).split( QLatin1Char('/') ); + if ( urlParts.size() != 3 ) + return 0; + //KMime::ContentIndex index( urlParts[1] ); + *path = KUrl::fromPercentEncoding( urlParts[2].toLatin1() ); + return w->nodeFromUrl( urlParts[1] ); } bool URLHandlerManager::BodyPartURLHandlerManager::handleClick( const KUrl & url, ViewerPrivate * w ) const { - QString path; - KMime::Content * node = partNodeFromXKMailUrl( url, w, &path ); - if ( !node ) - return false; + QString path; + KMime::Content * node = partNodeFromXKMailUrl( url, w, &path ); + if ( !node ) + return false; - PartNodeBodyPart part( w->message().get(), node, w->nodeHelper(), w->overrideCodec() ); - BodyPartHandlerList::const_iterator end( mHandlers.constEnd() ); - - for ( BodyPartHandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) { - if ( (*it)->handleClick( w->viewer(), &part, path ) ) - return true; - } + PartNodeBodyPart part( w->message().get(), node, w->nodeHelper(), w->overrideCodec() ); + BodyPartHandlerList::const_iterator end( mHandlers.constEnd() ); - return false; + for ( BodyPartHandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) { + if ( (*it)->handleClick( w->viewer(), &part, path ) ) + return true; + } + + return false; } bool URLHandlerManager::BodyPartURLHandlerManager::handleContextMenuRequest( const KUrl & url, const QPoint & p, ViewerPrivate * w ) const { - QString path; - KMime::Content * node = partNodeFromXKMailUrl( url, w, &path ); - if ( !node ) - return false; + QString path; + KMime::Content * node = partNodeFromXKMailUrl( url, w, &path ); + if ( !node ) + return false; - PartNodeBodyPart part( w->message().get(), node, w->nodeHelper(), w->overrideCodec() ); - BodyPartHandlerList::const_iterator end( mHandlers.constEnd() ); - for ( BodyPartHandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) - if ( (*it)->handleContextMenuRequest( &part, path, p ) ) - return true; - return false; + PartNodeBodyPart part( w->message().get(), node, w->nodeHelper(), w->overrideCodec() ); + BodyPartHandlerList::const_iterator end( mHandlers.constEnd() ); + for ( BodyPartHandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) + if ( (*it)->handleContextMenuRequest( &part, path, p ) ) + return true; + return false; } QString URLHandlerManager::BodyPartURLHandlerManager::statusBarMessage( const KUrl & url, ViewerPrivate * w ) const { - QString path; - KMime::Content * node = partNodeFromXKMailUrl( url, w, &path ); - if ( !node ) - return QString(); + QString path; + KMime::Content * node = partNodeFromXKMailUrl( url, w, &path ); + if ( !node ) + return QString(); - PartNodeBodyPart part( w->message().get(), node, w->nodeHelper(), w->overrideCodec() ); - BodyPartHandlerList::const_iterator end( mHandlers.constEnd() ); - for ( BodyPartHandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) { - const QString msg = (*it)->statusBarMessage( &part, path ); - if ( !msg.isEmpty() ) - return msg; - } - return QString(); + PartNodeBodyPart part( w->message().get(), node, w->nodeHelper(), w->overrideCodec() ); + BodyPartHandlerList::const_iterator end( mHandlers.constEnd() ); + for ( BodyPartHandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) { + const QString msg = (*it)->statusBarMessage( &part, path ); + if ( !msg.isEmpty() ) + return msg; + } + return QString(); } // @@ -327,99 +327,99 @@ // URLHandlerManager::URLHandlerManager() { - registerHandler( new KMailProtocolURLHandler() ); - registerHandler( new ExpandCollapseQuoteURLManager() ); - registerHandler( new SMimeURLHandler() ); - registerHandler( new MailToURLHandler() ); - registerHandler( new ContactUidURLHandler() ); - registerHandler( new HtmlAnchorHandler() ); - registerHandler( new AttachmentURLHandler() ); - registerHandler( mBodyPartURLHandlerManager = new BodyPartURLHandlerManager() ); - registerHandler( new ShowAuditLogURLHandler() ); - registerHandler( new InternalImageURLHandler ); - registerHandler( new KRunURLHandler() ); + registerHandler( new KMailProtocolURLHandler() ); + registerHandler( new ExpandCollapseQuoteURLManager() ); + registerHandler( new SMimeURLHandler() ); + registerHandler( new MailToURLHandler() ); + registerHandler( new ContactUidURLHandler() ); + registerHandler( new HtmlAnchorHandler() ); + registerHandler( new AttachmentURLHandler() ); + registerHandler( mBodyPartURLHandlerManager = new BodyPartURLHandlerManager() ); + registerHandler( new ShowAuditLogURLHandler() ); + registerHandler( new InternalImageURLHandler ); + registerHandler( new KRunURLHandler() ); } URLHandlerManager::~URLHandlerManager() { - for_each( mHandlers.begin(), mHandlers.end(), - DeleteAndSetToZero() ); + for_each( mHandlers.begin(), mHandlers.end(), + DeleteAndSetToZero() ); } void URLHandlerManager::registerHandler( const URLHandler * handler ) { - if ( !handler ) - return; - unregisterHandler( handler ); // don't produce duplicates - mHandlers.push_back( handler ); + if ( !handler ) + return; + unregisterHandler( handler ); // don't produce duplicates + mHandlers.push_back( handler ); } void URLHandlerManager::unregisterHandler( const URLHandler * handler ) { - // don't delete them, only remove them from the list! - mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() ); + // don't delete them, only remove them from the list! + mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() ); } void URLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) { - if ( mBodyPartURLHandlerManager ) - mBodyPartURLHandlerManager->registerHandler( handler ); + if ( mBodyPartURLHandlerManager ) + mBodyPartURLHandlerManager->registerHandler( handler ); } void URLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) { - if ( mBodyPartURLHandlerManager ) - mBodyPartURLHandlerManager->unregisterHandler( handler ); + if ( mBodyPartURLHandlerManager ) + mBodyPartURLHandlerManager->unregisterHandler( handler ); } bool URLHandlerManager::handleClick( const KUrl & url, ViewerPrivate * w ) const { - HandlerList::const_iterator end( mHandlers.constEnd() ); - for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) - if ( (*it)->handleClick( url, w ) ) - return true; - return false; + HandlerList::const_iterator end( mHandlers.constEnd() ); + for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) + if ( (*it)->handleClick( url, w ) ) + return true; + return false; } bool URLHandlerManager::handleShiftClick( const KUrl &url, ViewerPrivate *window ) const { - HandlerList::const_iterator end( mHandlers.constEnd() ); - for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) - if ( (*it)->handleShiftClick( url, window ) ) - return true; - return false; + HandlerList::const_iterator end( mHandlers.constEnd() ); + for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) + if ( (*it)->handleShiftClick( url, window ) ) + return true; + return false; } bool URLHandlerManager::willHandleDrag( const KUrl &url, ViewerPrivate *window ) const { - HandlerList::const_iterator end( mHandlers.constEnd() ); - - for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) - if ( (*it)->willHandleDrag( url, window ) ) - return true; - return false; + HandlerList::const_iterator end( mHandlers.constEnd() ); + + for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) + if ( (*it)->willHandleDrag( url, window ) ) + return true; + return false; } bool URLHandlerManager::handleDrag( const KUrl &url, ViewerPrivate *window ) const { - HandlerList::const_iterator end( mHandlers.constEnd() ); - for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) - if ( (*it)->handleDrag( url, window ) ) - return true; - return false; + HandlerList::const_iterator end( mHandlers.constEnd() ); + for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) + if ( (*it)->handleDrag( url, window ) ) + return true; + return false; } bool URLHandlerManager::handleContextMenuRequest( const KUrl & url, const QPoint & p, ViewerPrivate * w ) const { - HandlerList::const_iterator end( mHandlers.constEnd() ); - for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) - if ( (*it)->handleContextMenuRequest( url, p, w ) ) - return true; - return false; + HandlerList::const_iterator end( mHandlers.constEnd() ); + for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) + if ( (*it)->handleContextMenuRequest( url, p, w ) ) + return true; + return false; } QString URLHandlerManager::statusBarMessage( const KUrl & url, ViewerPrivate * w ) const { - HandlerList::const_iterator end( mHandlers.constEnd() ); - for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) { - const QString msg = (*it)->statusBarMessage( url, w ); - if ( !msg.isEmpty() ) - return msg; - } - return QString(); + HandlerList::const_iterator end( mHandlers.constEnd() ); + for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) { + const QString msg = (*it)->statusBarMessage( url, w ); + if ( !msg.isEmpty() ) + return msg; + } + return QString(); } @@ -435,156 +435,156 @@ #include namespace { - bool KMailProtocolURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const { +bool KMailProtocolURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const { if ( url.protocol() == QLatin1String( "kmail" ) ) { - if ( !w ) - return false; - const QString urlPath( url.path() ); - if ( urlPath == QLatin1String( "showHTML" ) ) { - w->setHtmlOverride( !w->htmlOverride() ); - w->update( Viewer::Force ); - return true; - } - else if ( urlPath == QLatin1String( "goOnline" ) ) { - w->goOnline(); - return true; - } - else if ( urlPath == QLatin1String( "goResourceOnline" ) ) { - w->goResourceOnline(); - return true; - } - else if ( urlPath == QLatin1String( "loadExternal" ) ) { - w->setHtmlLoadExtOverride( !w->htmlLoadExtOverride() ); - w->update( Viewer::Force ); - return true; - } - else if ( urlPath == QLatin1String( "decryptMessage" ) ) { - w->setDecryptMessageOverwrite( true ); - w->update( Viewer::Force ); - return true; - } - else if ( urlPath == QLatin1String( "showSignatureDetails" ) ) { - w->setShowSignatureDetails( true ); - w->update( Viewer::Force ); - return true; - } - else if ( urlPath == QLatin1String( "hideSignatureDetails" ) ) { - w->setShowSignatureDetails( false ); - w->update( Viewer::Force ); - return true; - } - else if ( urlPath == QLatin1String( "showAttachmentQuicklist" ) ) { - w->setShowAttachmentQuicklist( true ); - w->update( Viewer::Force ); - return true; - } - else if ( urlPath == QLatin1String( "hideAttachmentQuicklist" ) ) { - w->setShowAttachmentQuicklist( false ); - w->update( Viewer::Force ); - return true; - } - else if ( urlPath == QLatin1String( "showFullToAddressList" ) ) { - w->setShowFullToAddressList( true ); - w->update( Viewer::Force ); - return true; - } - else if ( urlPath == QLatin1String( "hideFullToAddressList" ) ) { - w->setShowFullToAddressList( false ); - w->update( Viewer::Force ); - return true; - } - else if ( urlPath == QLatin1String( "showFullCcAddressList" ) ) { - w->setShowFullCcAddressList( true ); - w->update( Viewer::Force ); - return true; - } - else if ( urlPath == QLatin1String( "hideFullCcAddressList" ) ) { - w->setShowFullCcAddressList( false ); - w->update( Viewer::Force ); - return true; - } - else if ( urlPath == QLatin1String( "showRawToltecMail" ) ) { - w->setShowRawToltecMail( true ); - w->update( Viewer::Force ); - return true; - } + if ( !w ) + return false; + const QString urlPath( url.path() ); + if ( urlPath == QLatin1String( "showHTML" ) ) { + w->setHtmlOverride( !w->htmlOverride() ); + w->update( Viewer::Force ); + return true; + } + else if ( urlPath == QLatin1String( "goOnline" ) ) { + w->goOnline(); + return true; + } + else if ( urlPath == QLatin1String( "goResourceOnline" ) ) { + w->goResourceOnline(); + return true; + } + else if ( urlPath == QLatin1String( "loadExternal" ) ) { + w->setHtmlLoadExtOverride( !w->htmlLoadExtOverride() ); + w->update( Viewer::Force ); + return true; + } + else if ( urlPath == QLatin1String( "decryptMessage" ) ) { + w->setDecryptMessageOverwrite( true ); + w->update( Viewer::Force ); + return true; + } + else if ( urlPath == QLatin1String( "showSignatureDetails" ) ) { + w->setShowSignatureDetails( true ); + w->update( Viewer::Force ); + return true; + } + else if ( urlPath == QLatin1String( "hideSignatureDetails" ) ) { + w->setShowSignatureDetails( false ); + w->update( Viewer::Force ); + return true; + } + else if ( urlPath == QLatin1String( "showAttachmentQuicklist" ) ) { + w->setShowAttachmentQuicklist( true ); + w->update( Viewer::Force ); + return true; + } + else if ( urlPath == QLatin1String( "hideAttachmentQuicklist" ) ) { + w->setShowAttachmentQuicklist( false ); + w->update( Viewer::Force ); + return true; + } + else if ( urlPath == QLatin1String( "showFullToAddressList" ) ) { + w->setShowFullToAddressList( true ); + w->update( Viewer::Force ); + return true; + } + else if ( urlPath == QLatin1String( "hideFullToAddressList" ) ) { + w->setShowFullToAddressList( false ); + w->update( Viewer::Force ); + return true; + } + else if ( urlPath == QLatin1String( "showFullCcAddressList" ) ) { + w->setShowFullCcAddressList( true ); + w->update( Viewer::Force ); + return true; + } + else if ( urlPath == QLatin1String( "hideFullCcAddressList" ) ) { + w->setShowFullCcAddressList( false ); + w->update( Viewer::Force ); + return true; + } + else if ( urlPath == QLatin1String( "showRawToltecMail" ) ) { + w->setShowRawToltecMail( true ); + w->update( Viewer::Force ); + return true; + } } return false; - } +} - QString KMailProtocolURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const { +QString KMailProtocolURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const { if ( url.protocol() == QLatin1String( "kmail" ) ) { - const QString urlPath( url.path() ); - if ( urlPath == QLatin1String( "showHTML" ) ) - return i18n("Turn on HTML rendering for this message."); - else if ( urlPath == QLatin1String( "loadExternal" ) ) - return i18n("Load external references from the Internet for this message."); - else if ( urlPath == QLatin1String( "goOnline" ) ) - return i18n("Work online."); - else if ( urlPath == QLatin1String( "goResourceOnline" ) ) - return i18n("Make account online."); - else if ( urlPath == QLatin1String( "decryptMessage" ) ) - return i18n("Decrypt message."); - else if ( urlPath == QLatin1String( "showSignatureDetails" ) ) - return i18n("Show signature details."); - else if ( urlPath == QLatin1String( "hideSignatureDetails" ) ) - return i18n("Hide signature details."); - else if ( urlPath == QLatin1String( "showAttachmentQuicklist" ) ) - return i18n( "Show attachment list." ); - else if ( urlPath == QLatin1String( "hideAttachmentQuicklist" ) ) - return i18n( "Hide attachment list." ); - else if ( urlPath == QLatin1String( "showFullToAddressList" ) ) - return i18n( "Show full \"To\" list" ); - else if ( urlPath == QLatin1String( "hideFullToAddressList" ) ) - return i18n( "Hide full \"To\" list" ); - else if ( urlPath == QLatin1String( "showFullCcAddressList" ) ) - return i18n( "Show full \"Cc\" list" ); - else if ( urlPath == QLatin1String( "hideFullCcAddressList" ) ) - return i18n( "Hide full \"Cc\" list" ); - else if ( urlPath == QLatin1String( "showRawToltecMail" ) ) - return i18n( "Show Raw Message" ); - else return QString(); + const QString urlPath( url.path() ); + if ( urlPath == QLatin1String( "showHTML" ) ) + return i18n("Turn on HTML rendering for this message."); + else if ( urlPath == QLatin1String( "loadExternal" ) ) + return i18n("Load external references from the Internet for this message."); + else if ( urlPath == QLatin1String( "goOnline" ) ) + return i18n("Work online."); + else if ( urlPath == QLatin1String( "goResourceOnline" ) ) + return i18n("Make account online."); + else if ( urlPath == QLatin1String( "decryptMessage" ) ) + return i18n("Decrypt message."); + else if ( urlPath == QLatin1String( "showSignatureDetails" ) ) + return i18n("Show signature details."); + else if ( urlPath == QLatin1String( "hideSignatureDetails" ) ) + return i18n("Hide signature details."); + else if ( urlPath == QLatin1String( "showAttachmentQuicklist" ) ) + return i18n( "Show attachment list." ); + else if ( urlPath == QLatin1String( "hideAttachmentQuicklist" ) ) + return i18n( "Hide attachment list." ); + else if ( urlPath == QLatin1String( "showFullToAddressList" ) ) + return i18n( "Show full \"To\" list" ); + else if ( urlPath == QLatin1String( "hideFullToAddressList" ) ) + return i18n( "Hide full \"To\" list" ); + else if ( urlPath == QLatin1String( "showFullCcAddressList" ) ) + return i18n( "Show full \"Cc\" list" ); + else if ( urlPath == QLatin1String( "hideFullCcAddressList" ) ) + return i18n( "Hide full \"Cc\" list" ); + else if ( urlPath == QLatin1String( "showRawToltecMail" ) ) + return i18n( "Show Raw Message" ); + else return QString(); } return QString() ; - } +} } namespace { - bool ExpandCollapseQuoteURLManager::handleClick( - const KUrl & url, ViewerPrivate * w ) const - { +bool ExpandCollapseQuoteURLManager::handleClick( + const KUrl & url, ViewerPrivate * w ) const +{ // kmail:levelquote/?num -> the level quote to collapse. // kmail:levelquote/?-num -> expand all levels quote. if ( url.protocol() == QLatin1String( "kmail" ) && url.path()==QLatin1String( "levelquote" ) ) { - const QString levelStr= url.query().mid( 1,url.query().length() ); - bool isNumber = false; - const int levelQuote= levelStr.toInt(&isNumber); - if ( isNumber ) - w->slotLevelQuote( levelQuote ); - return true; + const QString levelStr= url.query().mid( 1,url.query().length() ); + bool isNumber = false; + const int levelQuote= levelStr.toInt(&isNumber); + if ( isNumber ) + w->slotLevelQuote( levelQuote ); + return true; } return false; - } - QString ExpandCollapseQuoteURLManager::statusBarMessage( - const KUrl & url, ViewerPrivate * ) const - { - if ( url.protocol() == QLatin1String( "kmail" ) && url.path() == QLatin1String( "levelquote" ) ) - { +} +QString ExpandCollapseQuoteURLManager::statusBarMessage( + const KUrl & url, ViewerPrivate * ) const +{ + if ( url.protocol() == QLatin1String( "kmail" ) && url.path() == QLatin1String( "levelquote" ) ) + { const QString query= url.query(); if ( query.length()>=2 ) { - if ( query[ 1 ] ==QLatin1Char( '-' ) ) { - return i18n("Expand all quoted text."); - } - else { - return i18n("Collapse quoted text."); - } + if ( query[ 1 ] ==QLatin1Char( '-' ) ) { + return i18n("Expand all quoted text."); + } + else { + return i18n("Collapse quoted text."); + } } - } - return QString() ; - } + } + return QString() ; +} } @@ -593,26 +593,26 @@ QString& libName, QString& keyId ) { - static QString showCertMan(QLatin1String("showCertificate#")); - displayName.clear(); - libName.clear(); - keyId.clear(); - int i1 = aUrl.indexOf( showCertMan ); - if( -1 < i1 ) { - i1 += showCertMan.length(); - int i2 = aUrl.indexOf(QLatin1String(" ### "), i1); - if( i1 < i2 ) - { - displayName = aUrl.mid( i1, i2-i1 ); - i1 = i2+5; - i2 = aUrl.indexOf(QLatin1String(" ### "), i1); - if( i1 < i2 ) - { - libName = aUrl.mid( i1, i2-i1 ); - i2 += 5; + static QString showCertMan(QLatin1String("showCertificate#")); + displayName.clear(); + libName.clear(); + keyId.clear(); + int i1 = aUrl.indexOf( showCertMan ); + if( -1 < i1 ) { + i1 += showCertMan.length(); + int i2 = aUrl.indexOf(QLatin1String(" ### "), i1); + if( i1 < i2 ) + { + displayName = aUrl.mid( i1, i2-i1 ); + i1 = i2+5; + i2 = aUrl.indexOf(QLatin1String(" ### "), i1); + if( i1 < i2 ) + { + libName = aUrl.mid( i1, i2-i1 ); + i2 += 5; - keyId = aUrl.mid( i2 ); - /* + keyId = aUrl.mid( i2 ); + /* int len = aUrl.length(); if( len > i2+1 ) { keyId = aUrl.mid( i2, 2 ); @@ -624,62 +624,62 @@ } } */ - } + } + } } - } - return !keyId.isEmpty(); + return !keyId.isEmpty(); } namespace { - bool SMimeURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const { +bool SMimeURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const { if ( !url.hasRef() ) - return false; + return false; QString displayName, libName, keyId; if ( !foundSMIMEData( url.path() + QLatin1Char('#') + QUrl::fromPercentEncoding( url.ref().toLatin1() ), displayName, libName, keyId ) ) - return false; + return false; QStringList lst; lst << QLatin1String("-parent-windowid") << QString::number((qlonglong)w->viewer()->mainWindow()->winId() ) << QLatin1String("-query") << keyId; if ( !QProcess::startDetached( QLatin1String("kleopatra"),lst) ) - KMessageBox::error( w->mMainWindow, i18n("Could not start certificate manager. " - "Please check your installation."), - i18n("KMail Error") ); + KMessageBox::error( w->mMainWindow, i18n("Could not start certificate manager. " + "Please check your installation."), + i18n("KMail Error") ); return true; - } +} - QString SMimeURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const { +QString SMimeURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const { QString displayName, libName, keyId; if ( !foundSMIMEData( url.path() + QLatin1Char('#') + QUrl::fromPercentEncoding( url.ref().toLatin1() ), displayName, libName, keyId ) ) - return QString(); + return QString(); return i18n("Show certificate 0x%1", keyId ); - } +} } namespace { - bool HtmlAnchorHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const { +bool HtmlAnchorHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const { if ( url.hasHost() || !url.hasRef() ) - return false; + return false; w->htmlPart()->scrollToAnchor( url.ref() ); return true; - } +} } namespace { - QString MailToURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const { +QString MailToURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const { if ( url.protocol() == QLatin1String( "mailto" ) ) - return KPIMUtils::decodeMailtoUrl( url ); + return KPIMUtils::decodeMailtoUrl( url ); return QString(); - } +} } namespace { - static QString searchFullEmailByUid( const QString &uid ) - { +static QString searchFullEmailByUid( const QString &uid ) +{ QString fullEmail; Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob(); job->setLimit( 1 ); @@ -687,242 +687,242 @@ job->exec(); const KABC::Addressee::List res = job->contacts(); if ( !res.isEmpty() ) { - KABC::Addressee addr = res.first(); - fullEmail = addr.fullEmail(); + KABC::Addressee addr = res.first(); + fullEmail = addr.fullEmail(); } return fullEmail; - } +} - static void runKAddressBook( const KUrl &url ) - { +static void runKAddressBook( const KUrl &url ) +{ KPIM::OpenEmailAddressJob *job = new KPIM::OpenEmailAddressJob( url.path(), 0 ); job->start(); - } +} - bool ContactUidURLHandler::handleClick( const KUrl &url, ViewerPrivate * ) const - { +bool ContactUidURLHandler::handleClick( const KUrl &url, ViewerPrivate * ) const +{ if ( url.protocol() == QLatin1String( "uid" ) ) { - runKAddressBook( url ); - return true; + runKAddressBook( url ); + return true; } else { - return false; + return false; } - } +} - bool ContactUidURLHandler::handleContextMenuRequest( const KUrl &url, const QPoint &p, - ViewerPrivate * ) const - { +bool ContactUidURLHandler::handleContextMenuRequest( const KUrl &url, const QPoint &p, + ViewerPrivate * ) const +{ if ( url.protocol() != QLatin1String( "uid" ) || url.path().isEmpty() ) { - return false; + return false; } KMenu *menu = new KMenu(); QAction *open = - menu->addAction( KIcon( QLatin1String("view-pim-contacts") ), i18n( "&Open in Address Book" ) ); + menu->addAction( KIcon( QLatin1String("view-pim-contacts") ), i18n( "&Open in Address Book" ) ); #ifndef QT_NO_CLIPBOARD QAction *copy = - menu->addAction( KIcon( QLatin1String("edit-copy") ), i18n( "&Copy Email Address" ) ); + menu->addAction( KIcon( QLatin1String("edit-copy") ), i18n( "&Copy Email Address" ) ); #endif QAction *a = menu->exec( p ); if ( a == open ) { - runKAddressBook( url ); + runKAddressBook( url ); #ifndef QT_NO_CLIPBOARD } else if ( a == copy ) { - const QString fullEmail = searchFullEmailByUid( url.path() ); - if ( !fullEmail.isEmpty() ) { - QClipboard *clip = QApplication::clipboard(); - clip->setText( fullEmail, QClipboard::Clipboard ); - clip->setText( fullEmail, QClipboard::Selection ); - KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "Address copied to clipboard." ) ); - } + const QString fullEmail = searchFullEmailByUid( url.path() ); + if ( !fullEmail.isEmpty() ) { + QClipboard *clip = QApplication::clipboard(); + clip->setText( fullEmail, QClipboard::Clipboard ); + clip->setText( fullEmail, QClipboard::Selection ); + KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "Address copied to clipboard." ) ); + } #endif } delete menu; return true; - } +} - QString ContactUidURLHandler::statusBarMessage( const KUrl &url, ViewerPrivate * ) const - { +QString ContactUidURLHandler::statusBarMessage( const KUrl &url, ViewerPrivate * ) const +{ if ( url.protocol() == QLatin1String( "uid" ) ) { - return i18n( "Lookup the contact in KAddressbook" ); + return i18n( "Lookup the contact in KAddressbook" ); } else { - return QString(); + return QString(); } - } +} } namespace { - KMime::Content* AttachmentURLHandler::nodeForUrl( const KUrl &url, ViewerPrivate *w ) const - { - if ( !w || !w->mMessage ) - return 0; - if ( url.protocol() == QLatin1String( "attachment" ) ) - { - KMime::Content * node = w->nodeFromUrl( url ); - return node; - } - return 0; - } - - bool AttachmentURLHandler::attachmentIsInHeader( const KUrl &url ) const - { - bool inHeader = false; - const QString place = url.queryItem( QLatin1String("place") ).toLower(); - if ( !place.isNull() ) { - inHeader = ( place == QLatin1String( "header" ) ); - } - return inHeader; - } +KMime::Content* AttachmentURLHandler::nodeForUrl( const KUrl &url, ViewerPrivate *w ) const +{ + if ( !w || !w->mMessage ) + return 0; + if ( url.protocol() == QLatin1String( "attachment" ) ) + { + KMime::Content * node = w->nodeFromUrl( url ); + return node; + } + return 0; +} - bool AttachmentURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const - { +bool AttachmentURLHandler::attachmentIsInHeader( const KUrl &url ) const +{ + bool inHeader = false; + const QString place = url.queryItem( QLatin1String("place") ).toLower(); + if ( !place.isNull() ) { + inHeader = ( place == QLatin1String( "header" ) ); + } + return inHeader; +} + +bool AttachmentURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const +{ KMime::Content *node = nodeForUrl( url, w ); if ( !node ) - return false; + return false; const bool inHeader = attachmentIsInHeader( url ); const bool shouldShowDialog = !w->nodeHelper()->isNodeDisplayedEmbedded( node ) || !inHeader; if ( inHeader ) - w->scrollToAttachment( node ); + w->scrollToAttachment( node ); if ( shouldShowDialog ) - // PENDING(romain_kdab) : replace with toLocalFile() ? - w->openAttachment( node, w->nodeHelper()->tempFileUrlFromNode( node ).path() ); + // PENDING(romain_kdab) : replace with toLocalFile() ? + w->openAttachment( node, w->nodeHelper()->tempFileUrlFromNode( node ).path() ); return true; - } +} - bool AttachmentURLHandler::handleShiftClick( const KUrl &url, ViewerPrivate *window ) const - { +bool AttachmentURLHandler::handleShiftClick( const KUrl &url, ViewerPrivate *window ) const +{ KMime::Content *node = nodeForUrl( url, window ); if ( !node ) - return false; + return false; if ( !window ) - return false; + return false; Util::saveContents( window->viewer(), QList() << node ); return true; - } +} - bool AttachmentURLHandler::willHandleDrag( const KUrl &url, ViewerPrivate *window ) const - { +bool AttachmentURLHandler::willHandleDrag( const KUrl &url, ViewerPrivate *window ) const +{ return nodeForUrl( url, window ) != 0; - } +} - bool AttachmentURLHandler::handleDrag( const KUrl &url, ViewerPrivate *window ) const - { +bool AttachmentURLHandler::handleDrag( const KUrl &url, ViewerPrivate *window ) const +{ #ifndef QT_NO_DRAGANDDROP KMime::Content *node = nodeForUrl( url, window ); if ( !node ) - return false; + return false; const KUrl tUrl = window->nodeHelper()->tempFileUrlFromNode( node ); const QString fileName = tUrl.path(); if ( !fileName.isEmpty() ) { - QFile f(fileName); - f.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ReadUser|QFile::ReadGroup|QFile::ReadOther); - const QString icon = window->nodeHelper()->iconName( node, KIconLoader::Small ); - QDrag *drag = new QDrag( window->viewer() ); - QMimeData *mimeData = new QMimeData(); - mimeData->setUrls( QList() << tUrl ); - drag->setMimeData( mimeData ); - if ( !icon.isEmpty() ) { - drag->setPixmap( QPixmap( icon ) ); - } - drag->start(); - return true; + QFile f(fileName); + f.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ReadUser|QFile::ReadGroup|QFile::ReadOther); + const QString icon = window->nodeHelper()->iconName( node, KIconLoader::Small ); + QDrag *drag = new QDrag( window->viewer() ); + QMimeData *mimeData = new QMimeData(); + mimeData->setUrls( QList() << tUrl ); + drag->setMimeData( mimeData ); + if ( !icon.isEmpty() ) { + drag->setPixmap( QPixmap( icon ) ); + } + drag->start(); + return true; } else #endif - return false; - } + return false; +} - bool AttachmentURLHandler::handleContextMenuRequest( const KUrl & url, const QPoint & p, ViewerPrivate * w ) const - { +bool AttachmentURLHandler::handleContextMenuRequest( const KUrl & url, const QPoint & p, ViewerPrivate * w ) const +{ KMime::Content *node = nodeForUrl( url, w ); if ( !node ) - return false; + return false; // PENDING(romain_kdab) : replace with toLocalFile() ? w->showAttachmentPopup( node, w->nodeHelper()->tempFileUrlFromNode( node ).path(), p ); return true; - } +} - QString AttachmentURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * w ) const - { +QString AttachmentURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * w ) const +{ KMime::Content *node = nodeForUrl( url, w ); if ( !node ) - return QString(); + return QString(); const QString name = MessageViewer::NodeHelper::fileName( node ); if ( !name.isEmpty() ) - return i18n( "Attachment: %1", name ); + return i18n( "Attachment: %1", name ); else if ( dynamic_cast( node ) ) { - if ( node->header() ) { - return i18n( "Encapsulated Message (Subject: %1)", - node->header()->asUnicodeString() ); - } else { - return i18n( "Encapsulated Message" ); - } + if ( node->header() ) { + return i18n( "Encapsulated Message (Subject: %1)", + node->header()->asUnicodeString() ); + } else { + return i18n( "Encapsulated Message" ); + } } return i18n( "Unnamed attachment" ); - } +} } namespace { - static QString extractAuditLog( const KUrl & url ) { +static QString extractAuditLog( const KUrl & url ) { if ( url.protocol() != QLatin1String( "kmail" ) || url.path() != QLatin1String( "showAuditLog" ) ) - return QString(); + return QString(); assert( !url.queryItem( QLatin1String("log") ).isEmpty() ); return url.queryItem( QLatin1String("log") ); - } +} - bool ShowAuditLogURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const { +bool ShowAuditLogURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const { const QString auditLog = extractAuditLog( url ); if ( auditLog.isEmpty() ) return false; Kleo::MessageBox::auditLog( w->mMainWindow, auditLog ); return true; - } +} - bool ShowAuditLogURLHandler::handleContextMenuRequest( const KUrl & url, const QPoint &, ViewerPrivate * w ) const { +bool ShowAuditLogURLHandler::handleContextMenuRequest( const KUrl & url, const QPoint &, ViewerPrivate * w ) const { Q_UNUSED( w ); // disable RMB for my own links: return !extractAuditLog( url ).isEmpty(); - } +} - QString ShowAuditLogURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const { +QString ShowAuditLogURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const { if ( extractAuditLog( url ).isEmpty() ) - return QString(); + return QString(); else - return i18n("Show GnuPG Audit Log for this operation"); - } + return i18n("Show GnuPG Audit Log for this operation"); +} } namespace { - bool InternalImageURLHandler::handleDrag( const KUrl &url, ViewerPrivate *window ) const - { +bool InternalImageURLHandler::handleDrag( const KUrl &url, ViewerPrivate *window ) const +{ Q_UNUSED( window ); Q_UNUSED( url ); // This will only be called when willHandleDrag() was true. Return false here, that will // notify ViewerPrivate::eventFilter() that no drag was started. return false; - } +} - bool InternalImageURLHandler::willHandleDrag( const KUrl &url, ViewerPrivate *window ) const - { +bool InternalImageURLHandler::willHandleDrag( const KUrl &url, ViewerPrivate *window ) const +{ Q_UNUSED( window ); if ( url.protocol() == QLatin1String( "data" ) && url.path().startsWith( QLatin1String("image") ) ) - return true; + return true; const QString imagePath = KStandardDirs::locate( "data", QLatin1String("libmessageviewer/pics/") ); return url.path().contains( imagePath ); - } +} } namespace { - bool KRunURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const - { +bool KRunURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const +{ const QString protocol(url.protocol() ); if ( ( protocol == QLatin1String( "http" ) ) || ( protocol == QLatin1String( "https" ) ) || ( protocol == QLatin1String( "ftp" ) ) || ( protocol == QLatin1String( "file" ) ) || @@ -931,26 +931,26 @@ ( protocol == QLatin1String( "smb" ) ) || ( protocol == QLatin1String( "fish" ) ) || ( protocol == QLatin1String( "news" ) ) ) { - KPIM::BroadcastStatus::instance()->setTransientStatusMsg( i18n("Opening URL...")); - QTimer::singleShot( 2000, KPIM::BroadcastStatus::instance(), SLOT(reset()) ); + KPIM::BroadcastStatus::instance()->setTransientStatusMsg( i18n("Opening URL...")); + QTimer::singleShot( 2000, KPIM::BroadcastStatus::instance(), SLOT(reset()) ); - KMimeType::Ptr mime = KMimeType::findByUrl( url ); - if (mime->name() == QLatin1String("application/x-desktop") || - mime->name() == QLatin1String("application/x-executable") || - mime->name() == QLatin1String("application/x-ms-dos-executable") || - mime->name() == QLatin1String("application/x-shellscript") ) - { - if ( KMessageBox::warningYesNo( 0, i18nc( "@info", "Do you really want to execute %1?", - url.pathOrUrl() ), QString(), KGuiItem(i18n("Execute")), KStandardGuiItem::cancel() ) != KMessageBox::Yes) - return true; - } - if ( !MessageViewer::Util::handleUrlWithQDesktopServices( url.pathOrUrl() ) ) { - KRun *runner = new KRun( url, w->viewer() ); // will delete itself - runner->setRunExecutables( false ); - } + KMimeType::Ptr mime = KMimeType::findByUrl( url ); + if (mime->name() == QLatin1String("application/x-desktop") || + mime->name() == QLatin1String("application/x-executable") || + mime->name() == QLatin1String("application/x-ms-dos-executable") || + mime->name() == QLatin1String("application/x-shellscript") ) + { + if ( KMessageBox::warningYesNo( 0, i18nc( "@info", "Do you really want to execute %1?", + url.pathOrUrl() ), QString(), KGuiItem(i18n("Execute")), KStandardGuiItem::cancel() ) != KMessageBox::Yes) + return true; + } + if ( !MessageViewer::Util::handleUrlWithQDesktopServices( url.pathOrUrl() ) ) { + KRun *runner = new KRun( url, w->viewer() ); // will delete itself + runner->setRunExecutables( false ); + } - return true; + return true; } else return false; - } +} } diff -Nru kdepim-4.12.97/messageviewer/viewer/urlhandlermanager.h kdepim-4.13.0/messageviewer/viewer/urlhandlermanager.h --- kdepim-4.12.97/messageviewer/viewer/urlhandlermanager.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/urlhandlermanager.h 2014-04-10 07:40:20.000000000 +0000 @@ -42,12 +42,12 @@ class QPoint; namespace MessageViewer { - namespace Interface { - class BodyPartURLHandler; - } +namespace Interface { +class BodyPartURLHandler; +} - class ViewerPrivate; - class URLHandler; +class ViewerPrivate; +class URLHandler; } namespace MessageViewer { @@ -57,36 +57,36 @@ * @author Marc Mutz */ class URLHandlerManager { - static URLHandlerManager * self; + static URLHandlerManager * self; - URLHandlerManager(); + URLHandlerManager(); public: - ~URLHandlerManager(); + ~URLHandlerManager(); - static URLHandlerManager * instance() { - if ( !self ) - self = new URLHandlerManager(); - return self; - } - - void registerHandler( const URLHandler * handler ); - void unregisterHandler( const URLHandler * handler ); - - void registerHandler( const Interface::BodyPartURLHandler * handler ); - void unregisterHandler( const Interface::BodyPartURLHandler * handler ); - - bool handleClick( const KUrl & url, ViewerPrivate * w = 0 ) const; - bool handleShiftClick( const KUrl &url, ViewerPrivate *window = 0 ) const; - bool handleContextMenuRequest( const KUrl & url, const QPoint & p, ViewerPrivate * w = 0 ) const; - bool willHandleDrag( const KUrl &url, ViewerPrivate *window = 0 ) const; - bool handleDrag( const KUrl &url, ViewerPrivate *window = 0 ) const; - QString statusBarMessage( const KUrl & url, ViewerPrivate * w = 0 ) const; + static URLHandlerManager * instance() { + if ( !self ) + self = new URLHandlerManager(); + return self; + } + + void registerHandler( const URLHandler * handler ); + void unregisterHandler( const URLHandler * handler ); + + void registerHandler( const Interface::BodyPartURLHandler * handler ); + void unregisterHandler( const Interface::BodyPartURLHandler * handler ); + + bool handleClick( const KUrl & url, ViewerPrivate * w = 0 ) const; + bool handleShiftClick( const KUrl &url, ViewerPrivate *window = 0 ) const; + bool handleContextMenuRequest( const KUrl & url, const QPoint & p, ViewerPrivate * w = 0 ) const; + bool willHandleDrag( const KUrl &url, ViewerPrivate *window = 0 ) const; + bool handleDrag( const KUrl &url, ViewerPrivate *window = 0 ) const; + QString statusBarMessage( const KUrl & url, ViewerPrivate * w = 0 ) const; private: - typedef QVector HandlerList; - HandlerList mHandlers; - class BodyPartURLHandlerManager; - BodyPartURLHandlerManager * mBodyPartURLHandlerManager; + typedef QVector HandlerList; + HandlerList mHandlers; + class BodyPartURLHandlerManager; + BodyPartURLHandlerManager * mBodyPartURLHandlerManager; }; } diff -Nru kdepim-4.12.97/messageviewer/viewer/viewer_p.cpp kdepim-4.13.0/messageviewer/viewer/viewer_p.cpp --- kdepim-4.12.97/messageviewer/viewer/viewer_p.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/viewer_p.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -1535,7 +1535,7 @@ mViewer->setObjectName( QLatin1String("mViewer") ); mCreateTodo = new MessageViewer::TodoEdit(readerBox); - connect(mCreateTodo, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection,QString)), this, SLOT(slotCreateTodo(KCalCore::Todo::Ptr,Akonadi::Collection,QString))); + connect(mCreateTodo, SIGNAL(createTodo(KCalCore::Todo::Ptr,Akonadi::Collection)), this, SLOT(slotCreateTodo(KCalCore::Todo::Ptr,Akonadi::Collection))); mCreateTodo->setObjectName(QLatin1String("createtodowidget")); mCreateTodo->hide(); @@ -2762,15 +2762,9 @@ void ViewerPrivate::viewerSelectionChanged() { - if( mViewer->selectedText().isEmpty() ) - { - mActionCollection->action( QLatin1String("kmail_copy") )->setEnabled( false ); - } else { - mActionCollection->action( QLatin1String("kmail_copy") )->setEnabled( true ); - } + mActionCollection->action( QLatin1String("kmail_copy") )->setEnabled( !mViewer->selectedText().isEmpty() ); } - void ViewerPrivate::selectAll() { mViewer->selectAll(); @@ -3387,7 +3381,7 @@ } } -void ViewerPrivate::slotCreateTodo(const KCalCore::Todo::Ptr &todoPtr, const Akonadi::Collection &collection, const QString &urlMessageAkonadi) +void ViewerPrivate::slotCreateTodo(const KCalCore::Todo::Ptr &todoPtr, const Akonadi::Collection &collection) { CreateTodoJob *createJob = new CreateTodoJob(todoPtr, collection, mMessageItem, this); createJob->start(); diff -Nru kdepim-4.12.97/messageviewer/viewer/viewer_p.h kdepim-4.13.0/messageviewer/viewer/viewer_p.h --- kdepim-4.12.97/messageviewer/viewer/viewer_p.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/viewer/viewer_p.h 2014-04-10 07:40:20.000000000 +0000 @@ -496,7 +496,7 @@ void saveSplitterSizes() const; void slotGrantleeThemesUpdated(); - void slotCreateTodo(const KCalCore::Todo::Ptr &, const Akonadi::Collection &collection, const QString &urlMessageAkonadi); + void slotCreateTodo(const KCalCore::Todo::Ptr &, const Akonadi::Collection &collection); public slots: /** An URL has been activate with a click. */ diff -Nru kdepim-4.12.97/messageviewer/widgets/todoedit.cpp kdepim-4.13.0/messageviewer/widgets/todoedit.cpp --- kdepim-4.12.97/messageviewer/widgets/todoedit.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/widgets/todoedit.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -74,7 +74,7 @@ mCollectionCombobox->setMimeTypeFilter( QStringList() << KCalCore::Todo::todoMimeType() ); mCollectionCombobox->setObjectName(QLatin1String("akonadicombobox")); #ifndef QT_NO_ACCESSIBILITY - mCollectionCombobox->setAccessibleDescription( i18n("Select collection where Todo will stored.") ); + mCollectionCombobox->setAccessibleDescription( i18n("The most recently selected folder used for Todos.") ); #endif connect(mCollectionCombobox, SIGNAL(currentIndexChanged(int)), SLOT(slotCollectionChanged(int))); @@ -97,18 +97,6 @@ show(); } -void TodoEdit::setMessageUrlAkonadi(const QString &url) -{ - if (mMessageUrlAkonadi != url) { - mMessageUrlAkonadi = url; - } -} - -QString TodoEdit::messageUrlAkonadi() const -{ - return mMessageUrlAkonadi; -} - void TodoEdit::writeConfig() { MessageViewer::GlobalSettingsBase::self()->setLastSelectedFolder(mCollectionCombobox->currentCollection().id()); @@ -150,7 +138,6 @@ { if (mMessage != value) { mMessage = value; - mMessageUrlAkonadi.clear(); const KMime::Headers::Subject * const subject = mMessage ? mMessage->subject(false) : 0; if (subject) { mNoteEdit->setText(i18n("Reply to \"%1\"", subject->asUnicodeString())); @@ -168,7 +155,6 @@ writeConfig(); mNoteEdit->clear(); mMessage = KMime::Message::Ptr(); - mMessageUrlAkonadi.clear(); hide(); } @@ -187,7 +173,7 @@ if (!mNoteEdit->text().trimmed().isEmpty()) { KCalCore::Todo::Ptr todo( new KCalCore::Todo ); todo->setSummary(mNoteEdit->text()); - Q_EMIT createTodo(todo, collection, mMessageUrlAkonadi); + Q_EMIT createTodo(todo, collection); mNoteEdit->clear(); } } diff -Nru kdepim-4.12.97/messageviewer/widgets/todoedit.h kdepim-4.13.0/messageviewer/widgets/todoedit.h --- kdepim-4.12.97/messageviewer/widgets/todoedit.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/messageviewer/widgets/todoedit.h 2014-04-10 07:40:20.000000000 +0000 @@ -46,9 +46,6 @@ void writeConfig(); - void setMessageUrlAkonadi(const QString &url); - QString messageUrlAkonadi() const; - void showToDoWidget(); public Q_SLOTS: void slotCloseWidget(); @@ -58,7 +55,7 @@ void slotCollectionChanged(int); Q_SIGNALS: - void createTodo(const KCalCore::Todo::Ptr &todo, const Akonadi::Collection &collection, const QString &messageUrlAkonadi); + void createTodo(const KCalCore::Todo::Ptr &todo, const Akonadi::Collection &collection); void collectionChanged(const Akonadi::Collection &col); void messageChanged(const KMime::Message::Ptr &msg); @@ -66,7 +63,6 @@ bool eventFilter(QObject *object, QEvent *e); private: void readConfig(); - QString mMessageUrlAkonadi; Akonadi::Collection mCollection; KMime::Message::Ptr mMessage; KLineEdit *mNoteEdit; diff -Nru kdepim-4.12.97/noteshared/CMakeLists.txt kdepim-4.13.0/noteshared/CMakeLists.txt --- kdepim-4.12.97/noteshared/CMakeLists.txt 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/noteshared/CMakeLists.txt 2014-04-10 07:40:20.000000000 +0000 @@ -1,3 +1,5 @@ +project(noteshared) + include_directories( ${CMAKE_SOURCE_DIR}/pimcommon/ ) diff -Nru kdepim-4.12.97/noteshared/job/createnewnotejob.cpp kdepim-4.13.0/noteshared/job/createnewnotejob.cpp --- kdepim-4.12.97/noteshared/job/createnewnotejob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/noteshared/job/createnewnotejob.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -17,7 +17,7 @@ #include "createnewnotejob.h" #include "notesharedglobalconfig.h" - +#include "noteshared/attributes/showfoldernotesattribute.h" #include "dialog/selectednotefolderdialog.h" #include "akonadi_next/note.h" @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include @@ -76,8 +78,32 @@ } else { col = Akonadi::Collection(id); } + Akonadi::CollectionFetchJob *fetchCollection = new Akonadi::CollectionFetchJob( col, Akonadi::CollectionFetchJob::Base ); + connect(fetchCollection, SIGNAL(result(KJob*)), this, SLOT(slotFetchCollection(KJob*))); +} +void CreateNewNoteJob::slotFetchCollection(KJob* job) +{ + if (job->error()) { + qDebug()<<" Error during fetch"; + deleteLater(); + return; + } + Akonadi::CollectionFetchJob *fetchCollection = qobject_cast(job); + if (fetchCollection->collections().isEmpty()) { + qDebug()<<"No collection fetched"; + deleteLater(); + return; + } + Akonadi::Collection col = fetchCollection->collections().at(0); if (col.isValid()) { + if (!col.hasAttribute()) { + if (KMessageBox::Yes == KMessageBox::warningYesNo(0, i18n("Collection is hidden. New note will stored but not displaying. Do you want to show collection?"))) { + col.addAttribute(new NoteShared::ShowFolderNotesAttribute()); + Akonadi::CollectionModifyJob *job = new Akonadi::CollectionModifyJob( col ); + connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionModifyFinished(KJob*)) ); + } + } Akonadi::Item newItem; newItem.setMimeType( Akonotes::Note::mimeType() ); @@ -127,3 +153,10 @@ } deleteLater(); } + +void CreateNewNoteJob::slotCollectionModifyFinished(KJob *job) +{ + if (job->error()) { + kWarning() << job->errorString(); + } +} diff -Nru kdepim-4.12.97/noteshared/job/createnewnotejob.h kdepim-4.13.0/noteshared/job/createnewnotejob.h --- kdepim-4.12.97/noteshared/job/createnewnotejob.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/noteshared/job/createnewnotejob.h 2014-04-10 07:40:20.000000000 +0000 @@ -41,6 +41,8 @@ private slots: void slotNoteCreationFinished(KJob *); + void slotFetchCollection(KJob *job); + void slotCollectionModifyFinished(KJob *job); private: QString mTitle; QString mText; diff -Nru kdepim-4.12.97/pimcommon/autocorrection/autocorrection.cpp kdepim-4.13.0/pimcommon/autocorrection/autocorrection.cpp --- kdepim-4.12.97/pimcommon/autocorrection/autocorrection.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/autocorrection/autocorrection.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -83,18 +84,19 @@ } else if (space) { break; } - pos++; - iter++; + ++pos; + ++iter; } cursor.setPosition(pos + block.position(), QTextCursor::KeepAnchor); } -void AutoCorrection::autocorrect(bool htmlMode, QTextDocument& document, int position) +void AutoCorrection::autocorrect(bool htmlMode, QTextDocument& document, int &position) { if (!mEnabled) return; mCursor = QTextCursor(&document); + int oldPosition = position; selectWord(mCursor,position); mWord = mCursor.selectedText(); if (mWord.isEmpty()) @@ -127,6 +129,7 @@ if (mCursor.selectedText() != mWord) mCursor.insertText(mWord); + position = oldPosition; mCursor.endEditBlock(); } @@ -820,8 +823,8 @@ if (mAutoCorrectLang.isEmpty()) mAutoCorrectLang = kdelang; - qDebug()<<" fname :"< twoUpperLetterExceptions() const; QHash autocorrectEntries() const; - void autocorrect(bool htmlMode, QTextDocument &document, int position); + void autocorrect(bool htmlMode, QTextDocument &document, int &position); void writeConfig(); void addAutoCorrect(const QString& currentWord, const QString& replaceWord); diff -Nru kdepim-4.12.97/pimcommon/autocorrection/tests/autocorrection_gui.cpp kdepim-4.13.0/pimcommon/autocorrection/tests/autocorrection_gui.cpp --- kdepim-4.12.97/pimcommon/autocorrection/tests/autocorrection_gui.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/autocorrection/tests/autocorrection_gui.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -76,12 +76,17 @@ if((e->key() == Qt::Key_Space) || (e->key() == Qt::Key_Enter) || (e->key() == Qt::Key_Return)) { if(mAutoCorrection && mAutoCorrection->isEnabledAutoCorrection()) { const QTextCharFormat initialTextFormat = textCursor().charFormat(); - mAutoCorrection->autocorrect(acceptRichText(), *document(),textCursor().position()); + int position = textCursor().position(); + mAutoCorrection->autocorrect(acceptRichText(), *document(), position); + QTextCursor cur = textCursor(); + cur.setPosition(position); if (e->key() == Qt::Key_Space) { - textCursor().insertText(QLatin1String(" "), initialTextFormat); + cur.insertText(QLatin1String(" "), initialTextFormat); + setTextCursor(cur); return; } else { - textCursor().insertText(QLatin1String("\n"), initialTextFormat); + cur.insertText(QLatin1String("\n"), initialTextFormat); + setTextCursor(cur); return; } } diff -Nru kdepim-4.12.97/pimcommon/autocorrection/widgets/lineeditwithautocorrection.cpp kdepim-4.13.0/pimcommon/autocorrection/widgets/lineeditwithautocorrection.cpp --- kdepim-4.12.97/pimcommon/autocorrection/widgets/lineeditwithautocorrection.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/autocorrection/widgets/lineeditwithautocorrection.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -58,9 +58,13 @@ if ((e->key() == Qt::Key_Space) || (e->key() == Qt::Key_Enter) || (e->key() == Qt::Key_Return)) { if (mAutoCorrection) { // no Html format in subject. - mAutoCorrection->autocorrect(false, *document(),textCursor().position()); + int position = textCursor().position(); + mAutoCorrection->autocorrect(false, *document(), position); + QTextCursor cur = textCursor(); + cur.setPosition(position); if (e->key() == Qt::Key_Space) { - textCursor().insertText(QLatin1String(" ")); + cur.insertText(QLatin1String(" ")); + setTextCursor(cur); return; } } diff -Nru kdepim-4.12.97/pimcommon/autocorrection/widgets/richtexteditwithautocorrection.cpp kdepim-4.13.0/pimcommon/autocorrection/widgets/richtexteditwithautocorrection.cpp --- kdepim-4.12.97/pimcommon/autocorrection/widgets/richtexteditwithautocorrection.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/autocorrection/widgets/richtexteditwithautocorrection.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -64,18 +64,23 @@ if ((e->key() == Qt::Key_Space) || (e->key() == Qt::Key_Enter) || (e->key() == Qt::Key_Return)) { const QTextCharFormat initialTextFormat = textCursor().charFormat(); const bool richText = acceptRichText(); - mAutoCorrection->autocorrect(richText, *document(),textCursor().position()); + int position = textCursor().position(); + mAutoCorrection->autocorrect(richText, *document(), position); + QTextCursor cur = textCursor(); + cur.setPosition(position); if (e->key() == Qt::Key_Space) { if (richText && !isSpecial(initialTextFormat)) - textCursor().insertText(QLatin1String(" "), initialTextFormat); + cur.insertText(QLatin1String(" "), initialTextFormat); else - textCursor().insertText(QLatin1String(" ")); + cur.insertText(QLatin1String(" ")); + setTextCursor(cur); return; } else { if (richText && !isSpecial(initialTextFormat)) - textCursor().insertText(QLatin1String("\n"), initialTextFormat); + cur.insertText(QLatin1String("\n"), initialTextFormat); else - textCursor().insertText(QLatin1String("\n")); + cur.insertText(QLatin1String("\n")); + setTextCursor(cur); return; } } diff -Nru kdepim-4.12.97/pimcommon/CMakeLists.txt kdepim-4.13.0/pimcommon/CMakeLists.txt --- kdepim-4.12.97/pimcommon/CMakeLists.txt 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/CMakeLists.txt 2014-04-10 07:40:20.000000000 +0000 @@ -1,3 +1,4 @@ +project(pimcommon) include_directories( ${CMAKE_SOURCE_DIR}/libkdepim ${CMAKE_CURRENT_SOURCE_DIR}/util/ @@ -58,10 +59,6 @@ storageservice/settings/storagelistwidgetitem.cpp storageservice/settings/storageservicesettingswidget.cpp - storageservice/ubuntuone/ubuntuonestorageservice.cpp - storageservice/ubuntuone/ubuntuonejob.cpp - storageservice/ubuntuone/ubuntuoneutil.cpp - storageservice/yousendit/yousenditjob.cpp storageservice/yousendit/yousenditstorageservice.cpp storageservice/yousendit/yousenditutil.cpp @@ -240,11 +237,9 @@ add_subdirectory(storageservice/tests) add_subdirectory(storageservice/yousendit/tests) add_subdirectory(storageservice/webdav/tests) -add_subdirectory(storageservice/ubuntuone/tests) add_subdirectory(storageservice/box/tests) - add_subdirectory(storageservice/dropbox/icons/) -add_subdirectory(storageservice/ubuntuone/icons/) + if( LibKGAPI2_FOUND ) add_subdirectory(storageservice/gdrive/tests/) add_subdirectory(storageservice/gdrive/icons/) diff -Nru kdepim-4.12.97/pimcommon/storageservice/box/boxstorageservice.cpp kdepim-4.13.0/pimcommon/storageservice/box/boxstorageservice.cpp --- kdepim-4.12.97/pimcommon/storageservice/box/boxstorageservice.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/box/boxstorageservice.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -487,7 +487,6 @@ return cap; } - QString BoxStorageService::storageServiceName() const { return serviceName(); diff -Nru kdepim-4.12.97/pimcommon/storageservice/dropbox/dropboxjob.cpp kdepim-4.13.0/pimcommon/storageservice/dropbox/dropboxjob.cpp --- kdepim-4.12.97/pimcommon/storageservice/dropbox/dropboxjob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/dropbox/dropboxjob.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -231,7 +231,7 @@ void DropBoxJob::parseCopyFile(const QString &data) { - qDebug()<<" data :"<oauth2RedirectUrl(); } -QString StorageServiceJobConfig::ubuntuOneAttachmentVolume() const -{ - if (!mSettingsJob) { - qDebug()<<" settings job not registered"; - return QString(); - } - return mSettingsJob->ubuntuOneAttachmentVolume(); -} QString StorageServiceJobConfig::hubicScope() const { @@ -176,15 +168,6 @@ return mSettingsJob->hubicScope(); } -QString StorageServiceJobConfig::ubuntuOneTokenName() const -{ - if (!mSettingsJob) { - qDebug()<<" settings job not registered"; - return QString(); - } - return mSettingsJob->ubuntuOneTokenName(); -} - QString StorageServiceJobConfig::gdriveClientId() const { if (!mSettingsJob) { diff -Nru kdepim-4.12.97/pimcommon/storageservice/storageservicejobconfig.h kdepim-4.13.0/pimcommon/storageservice/storageservicejobconfig.h --- kdepim-4.12.97/pimcommon/storageservice/storageservicejobconfig.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/storageservicejobconfig.h 2014-04-10 07:40:20.000000000 +0000 @@ -45,9 +45,7 @@ QString hubicClientSecret() const; QString dropboxRootPath() const; QString oauth2RedirectUrl() const; - QString ubuntuOneAttachmentVolume() const; QString hubicScope() const; - QString ubuntuOneTokenName() const; QString gdriveClientId() const; QString gdriveClientSecret() const; diff -Nru kdepim-4.12.97/pimcommon/storageservice/storageservicemanager.cpp kdepim-4.13.0/pimcommon/storageservice/storageservicemanager.cpp --- kdepim-4.12.97/pimcommon/storageservice/storageservicemanager.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/storageservicemanager.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -28,7 +28,6 @@ #include "dropbox/dropboxstorageservice.h" #include "hubic/hubicstorageservice.h" -#include "ubuntuone/ubuntuonestorageservice.h" #include "yousendit/yousenditstorageservice.h" #include "webdav/webdavstorageservice.h" #include "box/boxstorageservice.h" @@ -334,10 +333,6 @@ if (!mListService.contains(serviceName(Hubic))) { storageService = new HubicStorageService(); } - } else if (service == serviceName(UbuntuOne)) { - if (!mListService.contains(serviceName(UbuntuOne))) { - storageService = new UbuntuoneStorageService(); - } } else if (service == serviceName(YouSendIt)) { if (!mListService.contains(serviceName(YouSendIt))) { storageService = new YouSendItStorageService(); @@ -378,8 +373,6 @@ return PimCommon::DropBoxStorageService::description(); case Hubic: return PimCommon::HubicStorageService::description(); - case UbuntuOne: - return PimCommon::UbuntuoneStorageService::description(); case WebDav: return PimCommon::WebDavStorageService::description(); case Box: @@ -404,8 +397,6 @@ return PimCommon::DropBoxStorageService::serviceUrl(); case Hubic: return PimCommon::HubicStorageService::serviceUrl(); - case UbuntuOne: - return PimCommon::UbuntuoneStorageService::serviceUrl(); case YouSendIt: return PimCommon::YouSendItStorageService::serviceUrl(); case WebDav: @@ -431,8 +422,6 @@ return PimCommon::DropBoxStorageService::serviceName(); case Hubic: return PimCommon::HubicStorageService::serviceName(); - case UbuntuOne: - return PimCommon::UbuntuoneStorageService::serviceName(); case YouSendIt: return PimCommon::YouSendItStorageService::serviceName(); case WebDav: @@ -457,8 +446,6 @@ return PimCommon::DropBoxStorageService::name(); case Hubic: return PimCommon::HubicStorageService::name(); - case UbuntuOne: - return PimCommon::UbuntuoneStorageService::name(); case YouSendIt: return PimCommon::YouSendItStorageService::name(); case WebDav: @@ -483,8 +470,6 @@ return PimCommon::DropBoxStorageService::iconName(); case Hubic: return PimCommon::HubicStorageService::iconName(); - case UbuntuOne: - return PimCommon::UbuntuoneStorageService::iconName(); case YouSendIt: return PimCommon::YouSendItStorageService::iconName(); case WebDav: @@ -509,8 +494,6 @@ return PimCommon::DropBoxStorageService::serviceCapabilities(); case Hubic: return PimCommon::HubicStorageService::serviceCapabilities(); - case UbuntuOne: - return PimCommon::UbuntuoneStorageService::serviceCapabilities(); case YouSendIt: return PimCommon::YouSendItStorageService::serviceCapabilities(); case WebDav: diff -Nru kdepim-4.12.97/pimcommon/storageservice/storageservicemanager.h kdepim-4.13.0/pimcommon/storageservice/storageservicemanager.h --- kdepim-4.12.97/pimcommon/storageservice/storageservicemanager.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/storageservicemanager.h 2014-04-10 07:40:20.000000000 +0000 @@ -33,7 +33,6 @@ Unknown = -1, DropBox = 0, Hubic, - UbuntuOne, YouSendIt, WebDav, Box, diff -Nru kdepim-4.12.97/pimcommon/storageservice/ubuntuone/icons/CMakeLists.txt kdepim-4.13.0/pimcommon/storageservice/ubuntuone/icons/CMakeLists.txt --- kdepim-4.12.97/pimcommon/storageservice/ubuntuone/icons/CMakeLists.txt 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/ubuntuone/icons/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -KDE4_INSTALL_ICONS( ${ICON_INSTALL_DIR} ) Binary files /tmp/stfVe9ZVrN/kdepim-4.12.97/pimcommon/storageservice/ubuntuone/icons/hi16-app-kdepim-ubuntuone.png and /tmp/_Cfz0gndqc/kdepim-4.13.0/pimcommon/storageservice/ubuntuone/icons/hi16-app-kdepim-ubuntuone.png differ Binary files /tmp/stfVe9ZVrN/kdepim-4.12.97/pimcommon/storageservice/ubuntuone/icons/hi24-app-kdepim-ubuntuone.png and /tmp/_Cfz0gndqc/kdepim-4.13.0/pimcommon/storageservice/ubuntuone/icons/hi24-app-kdepim-ubuntuone.png differ Binary files /tmp/stfVe9ZVrN/kdepim-4.12.97/pimcommon/storageservice/ubuntuone/icons/hi32-app-kdepim-ubuntuone.png and /tmp/_Cfz0gndqc/kdepim-4.13.0/pimcommon/storageservice/ubuntuone/icons/hi32-app-kdepim-ubuntuone.png differ Binary files /tmp/stfVe9ZVrN/kdepim-4.12.97/pimcommon/storageservice/ubuntuone/icons/hi48-app-kdepim-ubuntuone.png and /tmp/_Cfz0gndqc/kdepim-4.13.0/pimcommon/storageservice/ubuntuone/icons/hi48-app-kdepim-ubuntuone.png differ Binary files /tmp/stfVe9ZVrN/kdepim-4.12.97/pimcommon/storageservice/ubuntuone/icons/hi64-app-ubuntuone.png and /tmp/_Cfz0gndqc/kdepim-4.13.0/pimcommon/storageservice/ubuntuone/icons/hi64-app-ubuntuone.png differ diff -Nru kdepim-4.12.97/pimcommon/storageservice/ubuntuone/tests/CMakeLists.txt kdepim-4.13.0/pimcommon/storageservice/ubuntuone/tests/CMakeLists.txt --- kdepim-4.12.97/pimcommon/storageservice/ubuntuone/tests/CMakeLists.txt 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/ubuntuone/tests/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -include_directories(${CMAKE_SOURCE_DIR}/pimcommon/ -) - - -set(ubuntuone_gui_SRCS ubuntuone_gui.cpp ../../tests/servicetestwidget.cpp) -kde4_add_executable(ubuntuone_gui TEST ${ubuntuone_gui_SRCS}) -target_link_libraries(ubuntuone_gui - ${QT_QTTEST_LIBRARY} - ${QT_QTCORE_LIBRARY} - ${QT_QTGUI_LIBRARY} - ${QT_QTNETWORK_LIBRARY} - ${KDE4_KDECORE_LIBS} - ${KDE4_KDEUI_LIBS} - ${KDE4_KIO_LIBS} - pimcommon -) - diff -Nru kdepim-4.12.97/pimcommon/storageservice/ubuntuone/tests/ubuntuone_gui.cpp kdepim-4.13.0/pimcommon/storageservice/ubuntuone/tests/ubuntuone_gui.cpp --- kdepim-4.12.97/pimcommon/storageservice/ubuntuone/tests/ubuntuone_gui.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/ubuntuone/tests/ubuntuone_gui.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -/* - Copyright (c) 2013, 2014 Montel Laurent - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "ubuntuone_gui.h" -#include "pimcommon/storageservice/ubuntuone/ubuntuonestorageservice.h" -#include - -#include -#include -#include -#include - -UbuntuOneTestWidget::UbuntuOneTestWidget(QWidget *parent) - : ServiceTestWidget(parent) -{ - setStorageService(new PimCommon::UbuntuoneStorageService(this)); -} - -int main (int argc, char **argv) -{ - KCmdLineArgs::init(argc, argv, "UbuntuOne_gui", 0, ki18n("UbuntuOne_Gui"), - "1.0", ki18n("Test for short UbuntuOne")); - - KApplication app; - - UbuntuOneTestWidget *w = new UbuntuOneTestWidget; - w->show(); - return app.exec(); -} - diff -Nru kdepim-4.12.97/pimcommon/storageservice/ubuntuone/tests/ubuntuone_gui.h kdepim-4.13.0/pimcommon/storageservice/ubuntuone/tests/ubuntuone_gui.h --- kdepim-4.12.97/pimcommon/storageservice/ubuntuone/tests/ubuntuone_gui.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/ubuntuone/tests/ubuntuone_gui.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -/* - Copyright (c) 2013, 2014 Montel Laurent - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef TEST_UbuntuOne_GUI_H -#define TEST_UbuntuOne_GUI_H - -#include -#include "pimcommon/storageservice/tests/servicetestwidget.h" -class UbuntuOneTestWidget : public ServiceTestWidget -{ - Q_OBJECT -public: - explicit UbuntuOneTestWidget(QWidget *parent=0); -}; - -#endif diff -Nru kdepim-4.12.97/pimcommon/storageservice/ubuntuone/ubuntuonejob.cpp kdepim-4.13.0/pimcommon/storageservice/ubuntuone/ubuntuonejob.cpp --- kdepim-4.12.97/pimcommon/storageservice/ubuntuone/ubuntuonejob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/ubuntuone/ubuntuonejob.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,626 +0,0 @@ -/* - Copyright (c) 2013, 2014 Montel Laurent - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "ubuntuonejob.h" -#include "pimcommon/storageservice/authdialog/logindialog.h" -#include "pimcommon/storageservice/utils/storageserviceutils.h" -#include "pimcommon/storageservice/storageservicejobconfig.h" - -#include - -#include - -#include -#include -#include -#include -#include - -using namespace PimCommon; - -UbuntuOneJob::UbuntuOneJob(QObject *parent) - : PimCommon::StorageServiceAbstractJob(parent) -{ - mAttachmentVolume = PimCommon::StorageServiceJobConfig::self()->ubuntuOneAttachmentVolume(); - mOauthVersion = QLatin1String("1.0"); - mOauthSignatureMethod = QLatin1String("PLAINTEXT"); - mNonce = PimCommon::StorageServiceUtils::generateNonce(8); - mTimestamp = QString::number(QDateTime::currentMSecsSinceEpoch()/1000); - connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(slotSendDataFinished(QNetworkReply*))); - connect(mNetworkAccessManager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), SLOT(slotAuthenticationRequired(QNetworkReply*,QAuthenticator*))); -} - -UbuntuOneJob::~UbuntuOneJob() -{ - -} - -void UbuntuOneJob::copyFile(const QString &source, const QString &destination) -{ - mActionType = PimCommon::StorageServiceAbstract::CopyFile; - mError = false; - qDebug()<<" not implemented"; - Q_EMIT actionFailed(QLatin1String("Not Implemented")); - //TODO - deleteLater(); -} - -void UbuntuOneJob::copyFolder(const QString &source, const QString &destination) -{ - mActionType = PimCommon::StorageServiceAbstract::CopyFolder; - mError = false; - qDebug()<<" not implemented"; - Q_EMIT actionFailed(QLatin1String("Not Implemented")); - //TODO - deleteLater(); -} - -void UbuntuOneJob::requestTokenAccess() -{ - mActionType = PimCommon::StorageServiceAbstract::RequestToken; - mError = false; - QUrl url(QLatin1String("https://login.ubuntu.com/api/1.0/authentications")); - url.addQueryItem(QLatin1String("ws.op"), QLatin1String("authenticate")); - url.addQueryItem(QLatin1String("token_name"), QLatin1String("Ubuntu One @ ") + PimCommon::StorageServiceJobConfig::self()->ubuntuOneTokenName() ); - qDebug()<<" postData "<get(request); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); -} - -QNetworkReply *UbuntuOneJob::uploadFile(const QString &filename, const QString &uploadAsName, const QString &destination) -{ - mActionType = PimCommon::StorageServiceAbstract::UploadFile; - mError = false; - QFile *file = new QFile(filename); - if (file->exists()) { - mActionType = PimCommon::StorageServiceAbstract::UploadFile; - mError = false; - if (file->open(QIODevice::ReadOnly)) { - //TODO - delete file; - return 0; //TODO return QNetworkReply - } - } - qDebug()<<" upload file not implemented"; - Q_EMIT actionFailed(QLatin1String("Not Implemented")); - deleteLater(); - delete file; - return 0; -} - -void UbuntuOneJob::listFolder(const QString &folder) -{ - mActionType = PimCommon::StorageServiceAbstract::ListFolder; - mError = false; - QUrl url(QString::fromLatin1("https://one.ubuntu.com/api/file_storage/v1/~/Ubuntu%20One/%1/?include_children=true").arg(folder)); - url.addQueryItem(QLatin1String("oauth_consumer_key"), mCustomerKey); - url.addQueryItem(QLatin1String("oauth_nonce"), mNonce); - - addDefaultUrlItem(url); - QNetworkRequest request(url); - qDebug()<<" url "<get(request); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); -} - -void UbuntuOneJob::accountInfo() -{ - mActionType = PimCommon::StorageServiceAbstract::AccountInfo; - mError = false; - QUrl url(QLatin1String("https://one.ubuntu.com/api/quota/")); - url.addQueryItem(QLatin1String("oauth_consumer_key"), mCustomerKey); - url.addQueryItem(QLatin1String("oauth_nonce"), mNonce); - - addDefaultUrlItem(url); - - QNetworkRequest request(url); - qDebug()<<" url "<get(request); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); -} - -void UbuntuOneJob::createFolder(const QString &foldername, const QString &destination) -{ - mActionType = PimCommon::StorageServiceAbstract::CreateFolder; - mError = false; - if (foldername.isEmpty()) { - qDebug()<<" foldername is empty"; - } - QNetworkRequest request(QUrl(QString::fromLatin1("https://one.ubuntu.com/api/file_storage/v1/volumes/~/%1").arg(destination) + foldername)); - request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/x-www-form-urlencoded")); - QUrl postData; - const QString mAccessOauth = mCustomerSecret + QLatin1String("%26") + mTokenSecret; -/* - postData.addQueryItem(QLatin1String("oauth_signature"), mAccessOauth); - postData.addQueryItem(QLatin1String("oauth_signature_method"), mOauthSignatureMethod); - postData.addQueryItem(QLatin1String("oauth_token"), mToken); - - postData.addQueryItem(QLatin1String("token_secret"), mTokenSecret); - postData.addQueryItem(QLatin1String("consumer_secret"), mCustomerSecret); - postData.addQueryItem(QLatin1String("consumer_key"), mCustomerKey); - */ - postData.addQueryItem(QLatin1String("oauth_signature"), mAccessOauth); - postData.addQueryItem(QLatin1String("oauth_signature_method"), mOauthSignatureMethod); - postData.addQueryItem(QLatin1String("oauth_timestamp"), mTimestamp); - postData.addQueryItem(QLatin1String("oauth_version"), mOauthVersion); - postData.addQueryItem(QLatin1String("oauth_token"), mToken); - - QNetworkReply *reply = mNetworkAccessManager->put(request, postData.encodedQuery()); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); -} - -void UbuntuOneJob::shareLink(const QString &root, const QString &path) -{ - mActionType = PimCommon::StorageServiceAbstract::ShareLink; - mError = false; - qDebug()<<" not implemented"; - Q_EMIT actionFailed(QLatin1String("Not Implemented")); - deleteLater(); -} - -void UbuntuOneJob::initializeToken(const QString &customerSecret, const QString &token, const QString &customerKey, const QString &tokenSecret) -{ - mCustomerSecret = customerSecret; - mToken = token; - mCustomerKey = customerKey; - mTokenSecret = tokenSecret; -} - -void UbuntuOneJob::slotSendDataFinished(QNetworkReply *reply) -{ - const QString data = QString::fromUtf8(reply->readAll()); - reply->deleteLater(); - if (mError) { - qDebug()<<" error type "<put(request, postData.encodedQuery()); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); -} - -QNetworkReply *UbuntuOneJob::downloadFile(const QString &name, const QString &fileId, const QString &destination) -{ - mActionType = PimCommon::StorageServiceAbstract::DownLoadFile; - mError = false; -#if 0 - QFile *file = new QFile(destination); - if (file->exists()) { - mActionType = PimCommon::StorageServiceAbstract::UploadFile; - mError = false; - if (file->open(QIODevice::WriteOnly)) { - //TODO - delete file; - - } else { - delete file; - } - } - qDebug()<<" upload file not implemented"; - Q_EMIT actionFailed(QLatin1String("Not Implemented")); - deleteLater(); - return 0; - - -#endif - Q_EMIT actionFailed(QLatin1String("Not Implemented")); - deleteLater(); - return 0; -} - -void UbuntuOneJob::deleteFile(const QString &filename) -{ - mActionType = PimCommon::StorageServiceAbstract::DeleteFile; - mError = false; - - qDebug()<<" filename"<deleteResource(request); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); -} - -void UbuntuOneJob::deleteFolder(const QString &foldername) -{ - mActionType = PimCommon::StorageServiceAbstract::DeleteFolder; - mError = false; - QNetworkRequest request(QUrl(QLatin1String("https://one.ubuntu.com/api/file_storage/v1/volumes/~/Ubuntu One/") + foldername)); - request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/x-www-form-urlencoded")); - QUrl postData; - addDefaultUrlItem(postData); - QNetworkReply *reply = mNetworkAccessManager->deleteResource(request); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); -} - -void UbuntuOneJob::renameFolder(const QString &source, const QString &destination) -{ - mActionType = PimCommon::StorageServiceAbstract::RenameFolder; - mError = false; - qDebug()<<" not implemented"; - Q_EMIT actionFailed(QLatin1String("Not Implemented")); - //TODO - deleteLater(); -} - -void UbuntuOneJob::renameFile(const QString &oldName, const QString &newName) -{ - mActionType = PimCommon::StorageServiceAbstract::RenameFile; - mError = false; - QNetworkRequest request(QUrl(QLatin1String("https://one.ubuntu.com/api/file_storage/v1/volumes/~/Ubuntu One/") + oldName)); - request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/x-www-form-urlencoded")); - -#if 0 - - //https://one.ubuntu.com/api/file_storage/v1/~/Ubuntu One/ss?oauth_consumer_key=xze7Bw3& - oauth_nonce=13922099193c5& - oauth_signature=s4mmPGu164pA94R18SFfdqBW3As%3D& - oauth_signature_method=HMAC-SHA1& - oauth_timestamp=1392209919& - oauth_token=CLmkMwIYhWeQQVxbKRgYhwDeWpURoYvbEjfpzgUvgamUrJdMyo& - oauth_version=1.0 - - oauth_signature=aKYAypiqhSkxUYRUUGNbqRYJHnSRsi%26FhpzokZIMhMYlVXDgUGMnBgXetcxMHzmCTbWIYpVfKkvpfnBQa&token=MPNifxdxiGzAkyOGOshegdKkNxomjTTWAZKZYoMPqNsOhEODdB&token_secret=FhpzokZIMhMYlVXDgUGMnBgXetcxMHzmCTbWIYpVfKkvpfnBQa&consumer_secret=aKYAypiqhSkxUYRUUGNbqRYJHnSRsi&consumer_key=xze7Bw3; -#endif - QUrl postData; - - - - const QString mAccessOauth = mCustomerSecret + QLatin1String("%26") + mTokenSecret; - - postData.addQueryItem(QLatin1String("oauth_signature"), mAccessOauth); - - - - postData.addQueryItem(QLatin1String("oauth_token"), mToken); - postData.addQueryItem(QLatin1String("oauth_token_secret"), mTokenSecret); - //postData.addQueryItem(QLatin1String("oauth_consumer_secret"), mCustomerSecret); - postData.addQueryItem(QLatin1String("oauth_consumer_key"), mCustomerKey); - qDebug()<<" postData"<put(request, t.toUtf8()); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); -} - -void UbuntuOneJob::moveFolder(const QString &source, const QString &destination) -{ - mActionType = PimCommon::StorageServiceAbstract::MoveFolder; - mError = false; - qDebug()<<" not implemented"; - Q_EMIT actionFailed(QLatin1String("Not Implemented")); - //TODO - deleteLater(); - -} - -void UbuntuOneJob::moveFile(const QString &source, const QString &destination) -{ - mActionType = PimCommon::StorageServiceAbstract::MoveFile; - mError = false; - qDebug()<<" not implemented"; - Q_EMIT actionFailed(QLatin1String("Not Implemented")); - //TODO - deleteLater(); -} - -void UbuntuOneJob::parseCreateFolder(const QString &data) -{ - //TODO - qDebug()<<" data "< info = parser.parse(data.toUtf8(), &ok).toMap(); - PimCommon::AccountInfo accountInfo; - if (info.contains(QLatin1String("used"))) { - accountInfo.shared = info.value(QLatin1String("used")).toLongLong(); - } - if (info.contains(QLatin1String("total"))) { - accountInfo.accountSize = info.value(QLatin1String("total")).toLongLong(); - } - Q_EMIT accountInfoDone(accountInfo); - deleteLater(); -} - -void UbuntuOneJob::slotAuthenticationRequired(QNetworkReply *, QAuthenticator *auth) -{ - QPointer dlg = new LoginDialog; - dlg->setCaption(i18n("UbuntuOne")); - if (dlg->exec()) { - auth->setUser(dlg->username()); - auth->setPassword(dlg->password()); - } else { - Q_EMIT authorizationFailed(i18n("Authentication Canceled.")); - deleteLater(); - } - delete dlg; -} - -void UbuntuOneJob::parseRequestToken(const QString &data) -{ - QJson::Parser parser; - bool ok; - - QMap info = parser.parse(data.toUtf8(), &ok).toMap(); - qDebug()<<" info"<get(request); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); -} - -void UbuntuOneJob::addDefaultUrlItem(QUrl &url) -{ - const QString mAccessOauth = mCustomerSecret + QLatin1String("%26") + mTokenSecret; - url.addQueryItem(QLatin1String("oauth_signature"), mAccessOauth); - url.addQueryItem(QLatin1String("oauth_signature_method"), mOauthSignatureMethod); - url.addQueryItem(QLatin1String("oauth_timestamp"), mTimestamp); - url.addQueryItem(QLatin1String("oauth_version"), mOauthVersion); - url.addQueryItem(QLatin1String("oauth_token"), mToken); -} - -void UbuntuOneJob::parseAccessToken(const QString &data) -{ - qDebug()<<" data "< - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - - -#ifndef UBUNTUONEJOB_H -#define UBUNTUONEJOB_H - -#include "storageservice/job/storageserviceabstractjob.h" -#include "storageservice/storageserviceabstract.h" -#include -class QAuthenticator; -namespace PimCommon { -class UbuntuOneJob : public PimCommon::StorageServiceAbstractJob -{ - Q_OBJECT -public: - explicit UbuntuOneJob(QObject *parent=0); - ~UbuntuOneJob(); - - void requestTokenAccess(); - QNetworkReply *uploadFile(const QString &filename, const QString &uploadAsName, const QString &destination); - void listFolder(const QString &folder = QString()); - void accountInfo(); - void createFolder(const QString &foldername, const QString &destination); - void shareLink(const QString &root, const QString &path); - void createServiceFolder(); - QNetworkReply *downloadFile(const QString &name, const QString &fileId, const QString &destination); - void deleteFile(const QString &filename); - void deleteFolder(const QString &foldername); - void renameFolder(const QString &source, const QString &destination); - void renameFile(const QString &oldName, const QString &newName); - void moveFolder(const QString &source, const QString &destination); - void moveFile(const QString &source, const QString &destination); - void copyFile(const QString &source, const QString &destination); - void copyFolder(const QString &source, const QString &destination); - - void initializeToken(const QString &customerSecret, const QString &token, const QString &customerKey, const QString &tokenSecret); - -private Q_SLOTS: - void slotSendDataFinished(QNetworkReply *reply); - void slotAuthenticationRequired(QNetworkReply*,QAuthenticator*); - -Q_SIGNALS: - void authorizationDone(const QString &customerSecret, const QString &token, const QString &customerKey, const QString &tokenSecret); - -private: - void addDefaultUrlItem(QUrl &url); - void parseRequestToken(const QString &data); - void finishGetToken(); - void parseAccountInfo(const QString &data); - void parseListFolder(const QString &data); - void parseCreateFolder(const QString &data); - void parseUploadFile(const QString &data); - void parseAccessToken(const QString &data); - void parseCreateServiceFolder(const QString &data); - void parseDeleteFolder(const QString &data); - void parseRenameFile(const QString &data); - void parseRenameFolder(const QString &data); - void parseCopyFolder(const QString &data); - void parseCopyFile(const QString &data); - void parseMoveFolder(const QString &data); - void parseMoveFile(const QString &data); - void parseDeleteFile(const QString &data); - void parseDownloadFile(const QString &data); - void parseShareLink(const QString &data); - QString mCustomerSecret; - QString mToken; - QString mCustomerKey; - QString mTokenSecret; - QString mOauthVersion; - QString mOauthSignatureMethod; - QString mNonce; - QString mTimestamp; - QString mAttachmentVolume; -}; -} - -#endif // UBUNTUONEJOB_H diff -Nru kdepim-4.12.97/pimcommon/storageservice/ubuntuone/ubuntuonestorageservice.cpp kdepim-4.13.0/pimcommon/storageservice/ubuntuone/ubuntuonestorageservice.cpp --- kdepim-4.12.97/pimcommon/storageservice/ubuntuone/ubuntuonestorageservice.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/ubuntuone/ubuntuonestorageservice.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,542 +0,0 @@ -/* - Copyright (c) 2013, 2014 Montel Laurent - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "ubuntuonestorageservice.h" -#include "storageservice/widgets/storageservicetreewidget.h" -#include "storageservice/storageservicemanager.h" -#include "ubuntuonejob.h" -#include "pimcommon/storageservice/utils/storageserviceutils.h" - -#include "storageservice/settings/storageservicesettings.h" - -#include - -#include - -#include -#include -#include -#include - -#include - - -using namespace PimCommon; - -UbuntuoneStorageService::UbuntuoneStorageService(QObject *parent) - : PimCommon::StorageServiceAbstract(parent) -{ - readConfig(); -} - -UbuntuoneStorageService::~UbuntuoneStorageService() -{ -} - -void UbuntuoneStorageService::shutdownService() -{ - mCustomerSecret.clear(); - mToken.clear(); - mCustomerKey.clear(); - mTokenSecret.clear(); -} - -bool UbuntuoneStorageService::hasValidSettings() const -{ - return true; -} - -void UbuntuoneStorageService::readConfig() -{ - if (StorageServiceSettings::self()->createDefaultFolder()) { - KWallet::Wallet *wallet = StorageServiceSettings::self()->wallet(); - if (wallet) { - QStringList lst = wallet->entryList(); - if (lst.contains(storageServiceName())) { - QMap map; - wallet->readMap( storageServiceName(), map ); - if (map.contains(QLatin1String("Customer Secret"))) { - mCustomerSecret = map.value(QLatin1String("Customer Secret")); - } - if (map.contains(QLatin1String("Token"))) { - mToken = map.value(QLatin1String("Token")); - } - if (map.contains(QLatin1String("Customer Key"))) { - mCustomerKey = map.value(QLatin1String("Customer Key")); - } - if (map.contains(QLatin1String("Token Secret"))) { - mTokenSecret = map.value(QLatin1String("Token Secret")); - } - } - mNeedToReadConfigFirst = false; - } - } -} - -void UbuntuoneStorageService::slotAuthorizationDone(const QString &customerSecret, const QString &token, const QString &customerKey, const QString &tokenSecret) -{ - mCustomerSecret = customerSecret; - mToken = token; - mCustomerKey = customerKey; - mTokenSecret = tokenSecret; - - if (StorageServiceSettings::self()->createDefaultFolder()) { - const QString walletEntry = storageServiceName(); - KWallet::Wallet *wallet = StorageServiceSettings::self()->wallet(); - if (wallet) { - QMap map; - map[QLatin1String( "Customer Secret" )] = mCustomerSecret; - map[QLatin1String( "Token" )] = mToken; - map[QLatin1String( "Customer Key" )] = mCustomerKey; - map[QLatin1String( "Token Secret" )] = mTokenSecret; - wallet->writeMap( walletEntry, map); - } - } - emitAuthentificationDone(); -} - -void UbuntuoneStorageService::removeConfig() -{ - if (StorageServiceSettings::self()->createDefaultFolder()) { - const QString walletEntry = storageServiceName(); - KWallet::Wallet *wallet = StorageServiceSettings::self()->wallet(); - if (wallet) - wallet->removeEntry(walletEntry); - } -} - -void UbuntuoneStorageService::storageServiceauthentication() -{ - UbuntuOneJob *job = new UbuntuOneJob(this); - connect(job, SIGNAL(authorizationDone(QString,QString,QString,QString)), this, SLOT(slotAuthorizationDone(QString,QString,QString,QString))); - connect(job, SIGNAL(authorizationFailed(QString)), this, SLOT(slotAuthorizationFailed(QString))); - connect(job, SIGNAL(actionFailed(QString)), this, SLOT(slotActionFailed(QString))); - job->requestTokenAccess(); -} - -bool UbuntuoneStorageService::checkNeedAuthenticate() -{ - if (mNeedToReadConfigFirst) - readConfig(); - return mToken.isEmpty(); -} - -void UbuntuoneStorageService::storageServicelistFolder(const QString &folder) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(ListFolder); - mNextAction->setNextActionFolder(folder); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - connect(job, SIGNAL(listFolderDone(QVariant)), this, SLOT(slotListFolderDone(QVariant))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - job->listFolder(folder); - } -} - -void UbuntuoneStorageService::storageServicecreateFolder(const QString &name, const QString &destination) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(CreateFolder); - mNextAction->setNextActionName(name); - mNextAction->setNextActionFolder(destination); - - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(createFolderDone(QString)), this, SLOT(slotCreateFolderDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->createFolder(name, destination); - } -} - -void UbuntuoneStorageService::slotAuthorizationFailed(const QString &errorMessage) -{ - mCustomerSecret.clear(); - mToken.clear(); - mCustomerKey.clear(); - mTokenSecret.clear(); - emitAuthentificationFailder(errorMessage); -} - -void UbuntuoneStorageService::storageServiceaccountInfo() -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(AccountInfo); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job,SIGNAL(accountInfoDone(PimCommon::AccountInfo)), this, SLOT(slotAccountInfoDone(PimCommon::AccountInfo))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->accountInfo(); - } -} - -QString UbuntuoneStorageService::name() -{ - return i18n("Ubuntu One"); -} - -void UbuntuoneStorageService::storageServiceuploadFile(const QString &filename, const QString &uploadAsName, const QString &destination) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(UploadFile); - mNextAction->setNextActionName(filename); - mNextAction->setNextActionFolder(destination); - mNextAction->setUploadAsName(uploadAsName); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(uploadFileDone(QString)), this, SLOT(slotUploadFileDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - connect(job, SIGNAL(shareLinkDone(QString)), this, SLOT(slotShareLinkDone(QString))); - connect(job, SIGNAL(uploadDownloadFileProgress(qint64,qint64)), SLOT(slotuploadDownloadFileProgress(qint64,qint64))); - connect(job, SIGNAL(uploadFileFailed(QString)), this, SLOT(slotUploadFileFailed(QString))); - mUploadReply = job->uploadFile(filename, uploadAsName, destination); - } -} - -QString UbuntuoneStorageService::description() -{ - return i18n("UbuntuOne is a file hosting service operated by Canonical. that offers cloud storage, file synchronization, and client software."); -} - -QUrl UbuntuoneStorageService::serviceUrl() -{ - return QUrl(QLatin1String("https://one.ubuntu.com/")); -} - -QString UbuntuoneStorageService::serviceName() -{ - return QLatin1String("ubuntuone"); -} - -QString UbuntuoneStorageService::iconName() -{ - return QLatin1String("kdepim-ubuntuone"); -} - -StorageServiceAbstract::Capabilities UbuntuoneStorageService::serviceCapabilities() -{ - StorageServiceAbstract::Capabilities cap; - cap |= AccountInfoCapability; - //cap |= UploadFileCapability; - //cap |= DownloadFileCapability; - cap |= CreateFolderCapability; - cap |= DeleteFolderCapability; - cap |= ListFolderCapability; - //cap |= ShareLinkCapability; - cap |= DeleteFileCapability; - cap |= RenameFolderCapability; - cap |= RenameFileCapabilitity; - //cap |= MoveFileCapability; - //cap |= MoveFolderCapability; - //cap |= CopyFileCapability; - //cap |= CopyFolderCapability; - - return cap; -} - -void UbuntuoneStorageService::storageServiceShareLink(const QString &root, const QString &path) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(ShareLink); - mNextAction->setRootPath(root); - mNextAction->setPath(path); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(shareLinkDone(QString)), this, SLOT(slotShareLinkDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->shareLink(root, path); - } -} - -void UbuntuoneStorageService::storageServicedownloadFile(const QString &name, const QString &fileId, const QString &destination) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(DownLoadFile); - mNextAction->setNextActionName(name); - mNextAction->setDownloadDestination(destination); - mNextAction->setFileId(fileId); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(downLoadFileDone(QString)), this, SLOT(slotDownLoadFileDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - connect(job, SIGNAL(downLoadFileFailed(QString)), this, SLOT(slotDownLoadFileFailed(QString))); - connect(job, SIGNAL(uploadDownloadFileProgress(qint64,qint64)), SLOT(slotuploadDownloadFileProgress(qint64,qint64))); - mDownloadReply = job->downloadFile(name, fileId, destination); - } -} - -void UbuntuoneStorageService::storageServicecreateServiceFolder() -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(CreateServiceFolder); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(createFolderDone(QString)), this, SLOT(slotCreateFolderDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->createServiceFolder(); - } -} - -void UbuntuoneStorageService::storageServicedeleteFile(const QString &filename) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(DeleteFile); - mNextAction->setNextActionName(filename); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(deleteFileDone(QString)), SLOT(slotDeleteFileDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->deleteFile(filename); - } - -} - -void UbuntuoneStorageService::storageServicedeleteFolder(const QString &foldername) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(DeleteFile); - mNextAction->setNextActionFolder(foldername); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(deleteFolderDone(QString)), SLOT(slotDeleteFolderDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->deleteFolder(foldername); - } - -} - -void UbuntuoneStorageService::storageServiceRenameFolder(const QString &source, const QString &destination) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(RenameFolder); - mNextAction->setRenameFolder(source, destination); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(renameFolderDone(QString)), SLOT(slotRenameFolderDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->renameFolder(source, destination); - } -} - -void UbuntuoneStorageService::storageServiceRenameFile(const QString &source, const QString &destination) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(RenameFile); - mNextAction->setRenameFolder(source, destination); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(renameFileDone(QString)), SLOT(slotRenameFileDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->renameFile(source, destination); - } -} - -void UbuntuoneStorageService::storageServiceMoveFolder(const QString &source, const QString &destination) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(MoveFolder); - mNextAction->setRenameFolder(source, destination); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(moveFolderDone(QString)), SLOT(slotMoveFolderDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->moveFolder(source, destination); - } -} - -void UbuntuoneStorageService::storageServiceMoveFile(const QString &source, const QString &destination) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(MoveFolder); - mNextAction->setRenameFolder(source, destination); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(moveFileDone(QString)), SLOT(slotMoveFileDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->moveFile(source, destination); - } -} - -void UbuntuoneStorageService::storageServiceCopyFile(const QString &source, const QString &destination) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(CopyFile); - mNextAction->setRenameFolder(source, destination); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(copyFileDone(QString)), SLOT(slotCopyFileDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->copyFile(source, destination); - } -} - -void UbuntuoneStorageService::storageServiceCopyFolder(const QString &source, const QString &destination) -{ - if (checkNeedAuthenticate()) { - mNextAction->setNextActionType(CopyFolder); - mNextAction->setRenameFolder(source, destination); - storageServiceauthentication(); - } else { - UbuntuOneJob *job = new UbuntuOneJob(this); - job->initializeToken(mCustomerSecret, mToken, mCustomerKey, mTokenSecret); - connect(job, SIGNAL(copyFolderDone(QString)), SLOT(slotCopyFolderDone(QString))); - connect(job, SIGNAL(actionFailed(QString)), SLOT(slotActionFailed(QString))); - job->copyFolder(source, destination); - } -} - -StorageServiceAbstract::Capabilities UbuntuoneStorageService::capabilities() const -{ - return serviceCapabilities(); -} - -QString UbuntuoneStorageService::fillListWidget(StorageServiceTreeWidget *listWidget, const QVariant &data, const QString ¤tFolder) -{ - Q_UNUSED(currentFolder); - listWidget->clear(); - listWidget->createMoveUpItem(); - QJson::Parser parser; - bool ok; - QString parentFolder; - QMap info = parser.parse(data.toString().toUtf8(), &ok).toMap(); - //qDebug()<<" info "<addFolder(path, path); - if (map.contains(QLatin1String("when_created"))) { - const KDateTime t = KDateTime(QDateTime::fromString(map.value(QLatin1String("when_created")).toString(), QLatin1String("yyyy-MM-ddThh:mm:ssZ"))); - item->setDateCreated(t); - } - if (map.contains(QLatin1String("when_changed"))) { - const KDateTime t = KDateTime(QDateTime::fromString(map.value(QLatin1String("when_changed")).toString(), QLatin1String("yyyy-MM-ddThh:mm:ssZ"))); - item->setLastModification(t); - } - } else if (kind == QLatin1String("file")) { - const QString path = map.value(QLatin1String("path")).toString(); - item = listWidget->addFile(path, path); - if (map.contains(QLatin1String("size"))) { - item->setSize(map.value(QLatin1String("size")).toULongLong()); - } - if (map.contains(QLatin1String("when_created"))) { - const KDateTime t = KDateTime(QDateTime::fromString(map.value(QLatin1String("when_created")).toString(), QLatin1String("yyyy-MM-ddThh:mm:ssZ"))); - item->setDateCreated(t); - } - if (map.contains(QLatin1String("when_changed"))) { - const KDateTime t = KDateTime(QDateTime::fromString(map.value(QLatin1String("when_changed")).toString(), QLatin1String("yyyy-MM-ddThh:mm:ssZ"))); - item->setLastModification(t); - } - } else { - qDebug() <<" kind unknown "<setStoreInfo(map); - } - } - } - } - return parentFolder; -} - -QMap UbuntuoneStorageService::itemInformation(const QVariantMap &variantMap) -{ - qDebug()<<" variantMap "< information; - if (variantMap.contains(QLatin1String("kind"))) { - information.insert(PimCommon::StorageServiceUtils::propertyNameToI18n(PimCommon::StorageServiceUtils::Type), variantMap.value(QLatin1String("kind")).toString() == QLatin1String("file") ? i18n("File") : i18n("Folder")); - } - if (variantMap.contains(QLatin1String("volume_path"))) { - information.insert(i18n("Volume path:"), variantMap.value(QLatin1String("volume_path")).toString()); - } - if (variantMap.contains(QLatin1String("size"))) { - information.insert(PimCommon::StorageServiceUtils::propertyNameToI18n(PimCommon::StorageServiceUtils::Size), KGlobal::locale()->formatByteSize(variantMap.value(QLatin1String("size")).toULongLong())); - } - if (variantMap.contains(QLatin1String("when_created"))) { - const KDateTime t = KDateTime(QDateTime::fromString(variantMap.value(QLatin1String("when_created")).toString(), QLatin1String("yyyy-MM-ddThh:mm:ssZ"))); - information.insert(PimCommon::StorageServiceUtils::propertyNameToI18n(PimCommon::StorageServiceUtils::Created), KGlobal::locale()->formatDateTime(t)); - } - if (variantMap.contains(QLatin1String("when_changed"))) { - const KDateTime t = KDateTime(QDateTime::fromString(variantMap.value(QLatin1String("when_changed")).toString(), QLatin1String("yyyy-MM-ddThh:mm:ssZ"))); - information.insert(PimCommon::StorageServiceUtils::propertyNameToI18n(PimCommon::StorageServiceUtils::LastModified), KGlobal::locale()->formatDateTime(t)); - } - if (variantMap.contains(QLatin1String("is_public"))) { - const bool value = variantMap.value(QLatin1String("is_public")).toString() == QLatin1String("true"); - information.insert(i18n("File is public:"), (value ? i18n("Yes") : i18n("No"))); - if (variantMap.contains(QLatin1String("public_url"))) { - const QString publicurl = variantMap.value(QLatin1String("public_url")).toString(); - if (!publicurl.isEmpty()) - information.insert(i18n("Public link:"), publicurl); - } - } - return information; -} - -QString UbuntuoneStorageService::fileIdentifier(const QVariantMap &variantMap) -{ - return QString(); -} - -QString UbuntuoneStorageService::fileShareRoot(const QVariantMap &variantMap) -{ - return QString(); -} - -QString UbuntuoneStorageService::storageServiceName() const -{ - return serviceName(); -} - -KIcon UbuntuoneStorageService::icon() const -{ - return KIcon(UbuntuoneStorageService::iconName()); -} - -#include "moc_ubuntuonestorageservice.cpp" diff -Nru kdepim-4.12.97/pimcommon/storageservice/ubuntuone/ubuntuonestorageservice.h kdepim-4.13.0/pimcommon/storageservice/ubuntuone/ubuntuonestorageservice.h --- kdepim-4.12.97/pimcommon/storageservice/ubuntuone/ubuntuonestorageservice.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/ubuntuone/ubuntuonestorageservice.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -/* - Copyright (c) 2013, 2014 Montel Laurent - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef UBUNTUONESTORAGESERVICE_H -#define UBUNTUONESTORAGESERVICE_H - -#include "pimcommon/storageservice/storageserviceabstract.h" -#include "pimcommon_export.h" -namespace PimCommon { -class PIMCOMMON_EXPORT UbuntuoneStorageService : public PimCommon::StorageServiceAbstract -{ - Q_OBJECT -public: - explicit UbuntuoneStorageService(QObject *parent=0); - ~UbuntuoneStorageService(); - - static QString name(); - static QString description(); - static QUrl serviceUrl(); - static QString serviceName(); - static QString iconName(); - static StorageServiceAbstract::Capabilities serviceCapabilities(); - - void storageServiceuploadFile(const QString &filename, const QString &uploadAsName, const QString &destination = QString()); - void storageServiceaccountInfo(); - void storageServicecreateFolder(const QString &name, const QString &destination = QString()); - void storageServicelistFolder(const QString &folder); - void removeConfig(); - void storageServiceauthentication(); - void storageServiceShareLink(const QString &root, const QString &path); - void storageServicedownloadFile(const QString &name, const QString &fileId, const QString &destination); - void storageServicecreateServiceFolder(); - void storageServicedeleteFile(const QString &filename); - void storageServicedeleteFolder(const QString &foldername); - void storageServiceRenameFolder(const QString &source, const QString &destination); - void storageServiceRenameFile(const QString &source, const QString &destination); - void storageServiceMoveFolder(const QString &source, const QString &destination); - void storageServiceMoveFile(const QString &source, const QString &destination); - void storageServiceCopyFile(const QString &source, const QString &destination); - void storageServiceCopyFolder(const QString &source, const QString &destination); - - StorageServiceAbstract::Capabilities capabilities() const; - QString fillListWidget(StorageServiceTreeWidget *listWidget, const QVariant &data, const QString ¤tFolder); - QMap itemInformation(const QVariantMap &variantMap); - QString fileIdentifier(const QVariantMap &variantMap); - QString fileShareRoot(const QVariantMap &variantMap); - QString storageServiceName() const; - - KIcon icon() const; - - void shutdownService(); - bool hasValidSettings() const; - -private slots: - void slotAuthorizationDone(const QString &customerSecret, const QString &token, const QString &customerKey, const QString &tokenSecret); - void slotAuthorizationFailed(const QString &errorMessage); -private: - bool checkNeedAuthenticate(); - void readConfig(); - QString mCustomerSecret; - QString mToken; - QString mCustomerKey; - QString mTokenSecret; -}; -} - -#endif // UBUNTUONESTORAGESERVICE_H diff -Nru kdepim-4.12.97/pimcommon/storageservice/ubuntuone/ubuntuoneutil.cpp kdepim-4.13.0/pimcommon/storageservice/ubuntuone/ubuntuoneutil.cpp --- kdepim-4.12.97/pimcommon/storageservice/ubuntuone/ubuntuoneutil.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/ubuntuone/ubuntuoneutil.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -/* - Copyright (c) 2013, 2014 Montel Laurent - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - - -#include "ubuntuoneutil.h" - -#include -#include -#include - -QStringList PimCommon::UbuntuOneUtil::getListFolder(const QString &data) -{ - QJson::Parser parser; - bool ok; - - QMap info = parser.parse(data.toUtf8(), &ok).toMap(); - qDebug()<<" info "< lst = info.value(QLatin1String("user_node_paths")).toList(); - Q_FOREACH (const QVariant &v, lst) - listFolder.append(v.toString()); - } - return listFolder; -} diff -Nru kdepim-4.12.97/pimcommon/storageservice/ubuntuone/ubuntuoneutil.h kdepim-4.13.0/pimcommon/storageservice/ubuntuone/ubuntuoneutil.h --- kdepim-4.12.97/pimcommon/storageservice/ubuntuone/ubuntuoneutil.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/ubuntuone/ubuntuoneutil.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -/* - Copyright (c) 2013, 2014 Montel Laurent - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef UBUNTUONEUTIL_H -#define UBUNTUONEUTIL_H - -#include - -namespace PimCommon { -namespace UbuntuOneUtil -{ -QStringList getListFolder(const QString &data); -} -} - -#endif // UBUNTUONEUTIL_H diff -Nru kdepim-4.12.97/pimcommon/storageservice/webdav/webdavjob.cpp kdepim-4.13.0/pimcommon/storageservice/webdav/webdavjob.cpp --- kdepim-4.12.97/pimcommon/storageservice/webdav/webdavjob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/webdav/webdavjob.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -41,6 +41,7 @@ : PimCommon::StorageServiceAbstractJob(parent), mNbAuthCheck(0) { + mShareApi = QLatin1String("/ocs/v1.php/apps/files_sharing/api/v1/shares"); connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(slotSendDataFinished(QNetworkReply*))); connect(mNetworkAccessManager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), SLOT(slotAuthenticationRequired(QNetworkReply*,QAuthenticator*))); } @@ -413,95 +414,106 @@ } } -void WebDavJob::parseCreateServiceFolder(const QString &data) +void WebDavJob::parseCreateServiceFolder(const QString &/*data*/) { - //TODO Q_EMIT createFolderDone(QString()); deleteLater(); } void WebDavJob::parseShareLink(const QString &data) { - //TODO + qDebug()<<" data"<post(request, postData.encodedQuery()); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); } void WebDavJob::createServiceFolder() diff -Nru kdepim-4.12.97/pimcommon/storageservice/webdav/webdavjob.h kdepim-4.13.0/pimcommon/storageservice/webdav/webdavjob.h --- kdepim-4.12.97/pimcommon/storageservice/webdav/webdavjob.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/webdav/webdavjob.h 2014-04-10 07:40:20.000000000 +0000 @@ -103,6 +103,7 @@ QString mServiceLocation; QString mUserName; QString mPassword; + QString mShareApi; int mNbAuthCheck; }; diff -Nru kdepim-4.12.97/pimcommon/storageservice/webdav/webdavstorageservice.cpp kdepim-4.13.0/pimcommon/storageservice/webdav/webdavstorageservice.cpp --- kdepim-4.12.97/pimcommon/storageservice/webdav/webdavstorageservice.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/storageservice/webdav/webdavstorageservice.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -507,7 +507,7 @@ cap |= CreateFolderCapability; cap |= DeleteFolderCapability; cap |= ListFolderCapability; - cap |= ShareLinkCapability; + //cap |= ShareLinkCapability; cap |= DeleteFileCapability; cap |= RenameFolderCapability; cap |= RenameFileCapabilitity; diff -Nru kdepim-4.12.97/pimcommon/texteditor/plaintexteditor/plaintexteditor.cpp kdepim-4.13.0/pimcommon/texteditor/plaintexteditor/plaintexteditor.cpp --- kdepim-4.12.97/pimcommon/texteditor/plaintexteditor/plaintexteditor.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/texteditor/plaintexteditor/plaintexteditor.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -125,16 +125,17 @@ speakAction->setIcon(KIcon(QLatin1String("preferences-desktop-text-to-speech"))); speakAction->setEnabled(!emptyDocument ); connect( speakAction, SIGNAL(triggered(bool)), this, SLOT(slotSpeakText()) ); - addExtraMenuEntry(popup); + addExtraMenuEntry(popup, event->pos()); popup->exec( event->globalPos() ); delete popup; } } -void PlainTextEditor::addExtraMenuEntry(QMenu *menu) +void PlainTextEditor::addExtraMenuEntry(QMenu *menu, const QPoint &pos) { Q_UNUSED(menu); + Q_UNUSED(pos); } void PlainTextEditor::slotSpeakText() diff -Nru kdepim-4.12.97/pimcommon/texteditor/plaintexteditor/plaintexteditor.h kdepim-4.13.0/pimcommon/texteditor/plaintexteditor/plaintexteditor.h --- kdepim-4.12.97/pimcommon/texteditor/plaintexteditor/plaintexteditor.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/texteditor/plaintexteditor/plaintexteditor.h 2014-04-10 07:40:20.000000000 +0000 @@ -58,7 +58,7 @@ void slotSpellCheckerFinished(); protected: - virtual void addExtraMenuEntry(QMenu *menu); + virtual void addExtraMenuEntry(QMenu *menu, const QPoint &pos); protected: void contextMenuEvent( QContextMenuEvent *event ); diff -Nru kdepim-4.12.97/pimcommon/texteditor/richtexteditor/richtexteditor.cpp kdepim-4.13.0/pimcommon/texteditor/richtexteditor/richtexteditor.cpp --- kdepim-4.12.97/pimcommon/texteditor/richtexteditor/richtexteditor.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/texteditor/richtexteditor/richtexteditor.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -165,7 +165,7 @@ speakAction->setIcon(KIcon(QLatin1String("preferences-desktop-text-to-speech"))); speakAction->setEnabled(!emptyDocument ); connect( speakAction, SIGNAL(triggered(bool)), this, SLOT(slotSpeakText()) ); - addExtraMenuEntry(popup); + addExtraMenuEntry(popup, pos); popup->exec( pos ); delete popup; @@ -211,9 +211,10 @@ d->hasSpellCheckingSupport = check; } -void RichTextEditor::addExtraMenuEntry(QMenu *menu) +void RichTextEditor::addExtraMenuEntry(QMenu *menu, const QPoint &pos) { Q_UNUSED(menu); + Q_UNUSED(pos); } void RichTextEditor::slotUndoableClear() diff -Nru kdepim-4.12.97/pimcommon/texteditor/richtexteditor/richtexteditor.h kdepim-4.13.0/pimcommon/texteditor/richtexteditor/richtexteditor.h --- kdepim-4.12.97/pimcommon/texteditor/richtexteditor/richtexteditor.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/texteditor/richtexteditor/richtexteditor.h 2014-04-10 07:40:20.000000000 +0000 @@ -68,7 +68,7 @@ protected: - virtual void addExtraMenuEntry(QMenu *menu); + virtual void addExtraMenuEntry(QMenu *menu, const QPoint &pos); void contextMenuEvent( QContextMenuEvent *event ); void wheelEvent( QWheelEvent *event ); void focusInEvent( QFocusEvent *event ); diff -Nru kdepim-4.12.97/pimcommon/texteditor/richtexteditor/richtexteditorwidget.cpp kdepim-4.13.0/pimcommon/texteditor/richtexteditor/richtexteditorwidget.cpp --- kdepim-4.12.97/pimcommon/texteditor/richtexteditor/richtexteditorwidget.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/texteditor/richtexteditor/richtexteditorwidget.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -42,6 +42,11 @@ } +void RichTextEditorWidget::clear() +{ + mEditor->clear(); +} + void RichTextEditorWidget::setAcceptRichText(bool b) { mEditor->setAcceptRichText(b); diff -Nru kdepim-4.12.97/pimcommon/texteditor/richtexteditor/richtexteditorwidget.h kdepim-4.13.0/pimcommon/texteditor/richtexteditor/richtexteditorwidget.h --- kdepim-4.12.97/pimcommon/texteditor/richtexteditor/richtexteditorwidget.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimcommon/texteditor/richtexteditor/richtexteditorwidget.h 2014-04-10 07:40:20.000000000 +0000 @@ -34,6 +34,8 @@ explicit RichTextEditorWidget(RichTextEditor *customEditor, QWidget *parent=0); ~RichTextEditorWidget(); + void clear(); + RichTextEditor *editor() const { return mEditor; } void setReadOnly(bool readOnly); diff -Nru kdepim-4.12.97/pimsettingexporter/blogilo/exportblogilojob.cpp kdepim-4.13.0/pimsettingexporter/blogilo/exportblogilojob.cpp --- kdepim-4.12.97/pimsettingexporter/blogilo/exportblogilojob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimsettingexporter/blogilo/exportblogilojob.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -39,7 +39,7 @@ void ExportBlogiloJob::start() { - Q_EMIT title(i18n("Start export KNotes settings...")); + Q_EMIT title(i18n("Start export Blogilo settings...")); mArchiveDirectory = archive()->directory(); if (mTypeSelected & Utils::Config) { backupConfig(); diff -Nru kdepim-4.12.97/pimsettingexporter/pimsettingexporterwindow.cpp kdepim-4.13.0/pimsettingexporter/pimsettingexporterwindow.cpp --- kdepim-4.12.97/pimsettingexporter/pimsettingexporterwindow.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/pimsettingexporter/pimsettingexporterwindow.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -242,6 +242,8 @@ updateActions(true); mAction = Backup; mStoreIterator = mStored.constBegin(); + const QDateTime now = QDateTime::currentDateTime(); + slotAddInfo(QLatin1Char('[') + KGlobal::locale()->formatDateTime( now ) + QLatin1Char(']')); slotAddInfo(i18n("Start to backup data in \'%1\'", mArchiveStorage->filename())); slotAddEndLine(); //Add version @@ -458,6 +460,9 @@ qDebug()<<" version "<formatDateTime( now ) + QLatin1Char(']')); + slotAddInfo(i18n("Start to restore data from \'%1\'", mArchiveStorage->filename())); slotAddEndLine(); restoreNextStep(); diff -Nru kdepim-4.12.97/plugins/messageviewer/bodypartformatter/text_calendar.desktop kdepim-4.13.0/plugins/messageviewer/bodypartformatter/text_calendar.desktop --- kdepim-4.12.97/plugins/messageviewer/bodypartformatter/text_calendar.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/plugins/messageviewer/bodypartformatter/text_calendar.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -43,7 +43,7 @@ Name[pt]=Aplicação Sequência Binária Name[pt_BR]=Aplicativo Octetstream Name[ro]=Flux de octeți din aplicație -Name[ru]=Двоичный поток приложения +Name[ru]=Поток двоичных данных Name[sk]=Application Octetstream Name[sl]=Programski Octetstream Name[sr]=Програмски ток октета diff -Nru kdepim-4.12.97/plugins/messageviewer/bodypartformatter/text_vcard.desktop kdepim-4.13.0/plugins/messageviewer/bodypartformatter/text_vcard.desktop --- kdepim-4.12.97/plugins/messageviewer/bodypartformatter/text_vcard.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/plugins/messageviewer/bodypartformatter/text_vcard.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -43,7 +43,7 @@ Name[pt]=Aplicação Sequência Binária Name[pt_BR]=Aplicativo Octetstream Name[ro]=Flux de octeți din aplicație -Name[ru]=Двоичный поток приложения +Name[ru]=Поток двоичных данных Name[sk]=Application Octetstream Name[sl]=Programski Octetstream Name[sr]=Програмски ток октета diff -Nru kdepim-4.12.97/plugins/messageviewer/bodypartformatter/text_xdiff.desktop kdepim-4.13.0/plugins/messageviewer/bodypartformatter/text_xdiff.desktop --- kdepim-4.12.97/plugins/messageviewer/bodypartformatter/text_xdiff.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/plugins/messageviewer/bodypartformatter/text_xdiff.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -43,7 +43,7 @@ Name[pt]=Aplicação Sequência Binária Name[pt_BR]=Aplicativo Octetstream Name[ro]=Flux de octeți din aplicație -Name[ru]=Двоичный поток приложения +Name[ru]=Поток двоичных данных Name[sk]=Application Octetstream Name[sl]=Programski Octetstream Name[sr]=Програмски ток октета diff -Nru kdepim-4.12.97/sieveeditor/main.cpp kdepim-4.13.0/sieveeditor/main.cpp --- kdepim-4.12.97/sieveeditor/main.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/sieveeditor/main.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -45,6 +45,7 @@ } KUniqueApplication a; KGlobal::locale()->insertCatalog( QLatin1String("libksieve") ); + KGlobal::locale()->insertCatalog( QLatin1String("libpimcommon") ); SieveEditorMainWindow *mw = new SieveEditorMainWindow(); mw->show(); a.exec(); diff -Nru kdepim-4.12.97/sieveeditor/sieveeditor.desktop kdepim-4.13.0/sieveeditor/sieveeditor.desktop --- kdepim-4.12.97/sieveeditor/sieveeditor.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/sieveeditor/sieveeditor.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -11,6 +11,7 @@ Name[fi]=Sieve-muokkain Name[fr]=Éditeur Sieve Name[hu]=Sieve szerkesztő +Name[ia]=Editor de Sieve Name[it]=Editor Sieve Name[nb]=Sieve-redigering Name[nds]=Sieve-Editor @@ -18,6 +19,7 @@ Name[pl]=Edytor Sieve Name[pt]=Editor do Sieve Name[pt_BR]=Editor do Sieve +Name[ru]=Редактор фильтров Sieve Name[sk]=Editor Sieve Name[sr]=Сито уређивач Name[sr@ijekavian]=Сито уређивач @@ -43,6 +45,7 @@ GenericName[fi]=Sieve-muokkain GenericName[fr]=Éditeur Sieve GenericName[hu]=Sieve szerkesztő +GenericName[ia]=Editor de Sieve GenericName[it]=Editor Sieve GenericName[nb]=Sieve-redigering GenericName[nds]=Sieve-Editor @@ -50,6 +53,7 @@ GenericName[pl]=Edytor Sieve GenericName[pt]=Editor do Sieve GenericName[pt_BR]=Editor do Sieve +GenericName[ru]=Редактор фильтров Sieve GenericName[sk]=Editor Sieve GenericName[sr]=Сито уређивач GenericName[sr@ijekavian]=Сито уређивач diff -Nru kdepim-4.12.97/sieveeditor/sieveeditormainwindow.cpp kdepim-4.13.0/sieveeditor/sieveeditormainwindow.cpp --- kdepim-4.12.97/sieveeditor/sieveeditormainwindow.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/sieveeditor/sieveeditormainwindow.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -120,9 +120,11 @@ mDeleteScript = ac->addAction(QLatin1String("delete_script"), this, SLOT(slotDeleteScript())); mDeleteScript->setText(i18n("Delete Script")); + mDeleteScript->setShortcut(QKeySequence( Qt::Key_Delete )); mDeleteScript->setEnabled(false); mNewScript = ac->addAction(QLatin1String("create_new_script"), this, SLOT(slotCreateNewScript())); + mNewScript->setShortcut(QKeySequence( Qt::CTRL + Qt::Key_N )); mNewScript->setText(i18n("Create New Script...")); mNewScript->setEnabled(false); diff -Nru kdepim-4.12.97/sieveeditor/sieveeditorpagewidget.cpp kdepim-4.13.0/sieveeditor/sieveeditorpagewidget.cpp --- kdepim-4.12.97/sieveeditor/sieveeditorpagewidget.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/sieveeditor/sieveeditorpagewidget.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -168,6 +168,5 @@ void SieveEditorPageWidget::slotValueChanged() { - qDebug()<<"void SieveEditorPageWidget::slotValueChanged() "; setModified(true); } diff -Nru kdepim-4.12.97/storageservicemanager/data/storageservicemanager.notifyrc kdepim-4.13.0/storageservicemanager/data/storageservicemanager.notifyrc --- kdepim-4.12.97/storageservicemanager/data/storageservicemanager.notifyrc 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/storageservicemanager/data/storageservicemanager.notifyrc 2014-04-10 07:40:20.000000000 +0000 @@ -11,11 +11,15 @@ Comment[fi]=Tallennuspalveluiden hallinta Comment[fr]=StorageServiceManager Comment[hu]=Tároló szolgáltatás kezelő +Comment[ia]=StorageServiceManager +Comment[it]=StorageServiceManager +Comment[nb]=Behandler for lagringstjeneste Comment[nds]=Datenaflaag-Deenstpleger Comment[nl]=Beheerder van opslagservice Comment[pl]=Usługa zarządcy przechowywania Comment[pt]=Gestor de Serviços de Armazenamento Comment[pt_BR]=Gerenciador de Serviços de Armazenamento +Comment[ru]=Служба хранения данных Comment[sk]=Správca úložných služieb Comment[sr]=Менаџер складишног сервиса Comment[sr@ijekavian]=Менаџер складишног сервиса @@ -38,11 +42,15 @@ Name[fi]=Toiminto epäonnistui Name[fr]=L'action a échoué Name[hu]=A művelet meghiúsult +Name[ia]=Action falleva +Name[it]=Azione non riuscita +Name[nb]=Handling mislyktes Name[nds]=Akschonen fehlslaan Name[nl]=Actie is mislukt Name[pl]=Nieudane działanie Name[pt]=Acção sem Sucesso Name[pt_BR]=Ação com falhas +Name[ru]=Ошибка операции Name[sk]=Akcia zlyhala Name[sr]=Радња пропала Name[sr@ijekavian]=Радња пропала @@ -62,11 +70,15 @@ Comment[fi]=Tapahtui virhe Comment[fr]=Une erreur s'est produite Comment[hu]=Egy hiba tért vissza +Comment[ia]=Il retornava un error +Comment[it]=È stato restituito un errore +Comment[nb]=Det ble returnert en feil Comment[nds]=En Fehler wöör torüchgeven Comment[nl]=Er kwam een fout terug Comment[pl]=Zwrócono błąd Comment[pt]=Foi devolvido um erro Comment[pt_BR]=Ocorreu um erro +Comment[ru]=Произошла ошибка Comment[sk]=Nastala chyba Comment[sr]=Враћена је грешка Comment[sr@ijekavian]=Враћена је грешка diff -Nru kdepim-4.12.97/storageservicemanager/main.cpp kdepim-4.13.0/storageservicemanager/main.cpp --- kdepim-4.12.97/storageservicemanager/main.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/storageservicemanager/main.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -46,6 +46,7 @@ KUniqueApplication a; StorageServiceManagerMainWindow *mw = new StorageServiceManagerMainWindow(); KGlobal::locale()->insertCatalog( QLatin1String("libpimcommon") ); + KGlobal::locale()->insertCatalog( QLatin1String("libkgapi") ); mw->show(); a.exec(); } diff -Nru kdepim-4.12.97/storageservicemanager/storageservicemanager.desktop kdepim-4.13.0/storageservicemanager/storageservicemanager.desktop --- kdepim-4.12.97/storageservicemanager/storageservicemanager.desktop 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/storageservicemanager/storageservicemanager.desktop 2014-04-10 07:40:20.000000000 +0000 @@ -11,12 +11,15 @@ Name[fi]=Tallennuspalvelun hallinta Name[fr]=Gestionnaire de service de stockage Name[hu]=Tároló szolgáltatás kezelő +Name[ia]=Gerente de Servicio de immagazinage +Name[it]=Gestore dei servizi di memorizzazione Name[nb]=Behandler for lagringstjeneste Name[nds]=Datenaflaag-Deenstpleger Name[nl]=Beheerder van opslagservice Name[pl]=Usługa zarządcy przechowywania Name[pt]=Gestor de Serviços de Armazenamento Name[pt_BR]=Gerenciador de Serviços de Armazenamento +Name[ru]=Служба хранения данных Name[sk]=Správca úložných služieb Name[sr]=Менаџер складишног сервиса Name[sr@ijekavian]=Менаџер складишног сервиса @@ -42,12 +45,15 @@ GenericName[fi]=Tallennuspalvelun hallinta GenericName[fr]=Gestionnaire de service de stockage GenericName[hu]=Tároló szolgáltatás kezelő +GenericName[ia]=Gerente de Servicio de immagazinage +GenericName[it]=Gestore dei servizi di memorizzazione GenericName[nb]=Behandler for lagringstjeneste GenericName[nds]=Datenaflaag-Deenstpleger GenericName[nl]=Beheerder van opslagservice GenericName[pl]=Usługa zarządcy przechowywania GenericName[pt]=Gestor de Serviços de Armazenamento GenericName[pt_BR]=Gerenciador de Serviços de Armazenamento +GenericName[ru]=Служба хранения данных GenericName[sk]=Správca úložných služieb GenericName[sr]=Менаџер складишног сервиса GenericName[sr@ijekavian]=Менаџер складишног сервиса diff -Nru kdepim-4.12.97/storageservicemanager/storageservicemanagersettingsjob.cpp kdepim-4.13.0/storageservicemanager/storageservicemanagersettingsjob.cpp --- kdepim-4.12.97/storageservicemanager/storageservicemanagersettingsjob.cpp 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/storageservicemanager/storageservicemanagersettingsjob.cpp 2014-04-10 07:40:20.000000000 +0000 @@ -82,20 +82,12 @@ return QLatin1String("https://bugs.kde.org/"); } -QString StorageServiceManagerSettingsJob::ubuntuOneAttachmentVolume() const -{ - return QLatin1String("/~/KMail Attachments"); -} QString StorageServiceManagerSettingsJob::hubicScope() const { return QLatin1String("usage.r,account.r,credentials.r,links.wd"); } -QString StorageServiceManagerSettingsJob::ubuntuOneTokenName() const -{ - return QLatin1String("kde storagemanager"); -} QString StorageServiceManagerSettingsJob::gdriveClientId() const { diff -Nru kdepim-4.12.97/storageservicemanager/storageservicemanagersettingsjob.h kdepim-4.13.0/storageservicemanager/storageservicemanagersettingsjob.h --- kdepim-4.12.97/storageservicemanager/storageservicemanagersettingsjob.h 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/storageservicemanager/storageservicemanagersettingsjob.h 2014-04-10 07:40:20.000000000 +0000 @@ -40,9 +40,7 @@ QString hubicClientSecret() const; QString dropboxRootPath() const; QString oauth2RedirectUrl() const; - QString ubuntuOneAttachmentVolume() const; QString hubicScope() const; - QString ubuntuOneTokenName() const; QString gdriveClientId() const; QString gdriveClientSecret() const; QString defaultUploadFolder() const; diff -Nru kdepim-4.12.97/templateparser/CMakeLists.txt kdepim-4.13.0/templateparser/CMakeLists.txt --- kdepim-4.12.97/templateparser/CMakeLists.txt 2014-03-26 19:52:02.000000000 +0000 +++ kdepim-4.13.0/templateparser/CMakeLists.txt 2014-04-10 07:40:20.000000000 +0000 @@ -1,3 +1,4 @@ +project(templateparser) add_definitions( -DQT_NO_CAST_FROM_ASCII ) add_definitions( -DQT_NO_CAST_TO_ASCII )