akonadi
conflictresolvedialog.cpp
00001 /* 00002 Copyright (c) 2010 KDAB 00003 Author: Tobias Koenig <tokoe@kde.org> 00004 00005 This library is free software; you can redistribute it and/or modify it 00006 under the terms of the GNU Library General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or (at your 00008 option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, but WITHOUT 00011 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to the 00017 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00018 02110-1301, USA. 00019 */ 00020 00021 #include "conflictresolvedialog_p.h" 00022 00023 #include "abstractdifferencesreporter.h" 00024 #include "differencesalgorithminterface.h" 00025 #include "typepluginloader_p.h" 00026 00027 #include <QtGui/QVBoxLayout> 00028 #include <QtGui/QLabel> 00029 00030 #include <kcolorscheme.h> 00031 #include <klocale.h> 00032 #include <kpushbutton.h> 00033 #include <ktextbrowser.h> 00034 00035 using namespace Akonadi; 00036 00037 static inline QString textToHTML( const QString &text ) 00038 { 00039 return Qt::convertFromPlainText( text ); 00040 } 00041 00042 class HtmlDifferencesReporter : public AbstractDifferencesReporter 00043 { 00044 public: 00045 HtmlDifferencesReporter() 00046 { 00047 } 00048 00049 QString toHtml() const 00050 { 00051 return header() + mContent + footer(); 00052 } 00053 00054 void setPropertyNameTitle( const QString &title ) 00055 { 00056 mNameTitle = title; 00057 } 00058 00059 void setLeftPropertyValueTitle( const QString &title ) 00060 { 00061 mLeftTitle = title; 00062 } 00063 00064 void setRightPropertyValueTitle( const QString &title ) 00065 { 00066 mRightTitle = title; 00067 } 00068 00069 void addProperty( Mode mode, const QString &name, const QString &leftValue, const QString &rightValue ) 00070 { 00071 switch ( mode ) { 00072 case NormalMode: 00073 mContent.append( QString::fromLatin1( "<tr><td align=\"right\"><b>%1:</b></td><td>%2</td><td></td><td>%3</td></tr>" ) 00074 .arg( name ) 00075 .arg( textToHTML( leftValue ) ) 00076 .arg( textToHTML( rightValue ) ) ); 00077 break; 00078 case ConflictMode: 00079 mContent.append( QString::fromLatin1( "<tr><td align=\"right\"><b>%1:</b></td><td bgcolor=\"#ff8686\">%2</td><td></td><td bgcolor=\"#ff8686\">%3</td></tr>" ) 00080 .arg( name ) 00081 .arg( textToHTML( leftValue ) ) 00082 .arg( textToHTML( rightValue ) ) ); 00083 break; 00084 case AdditionalLeftMode: 00085 mContent.append( QString::fromLatin1( "<tr><td align=\"right\"><b>%1:</b></td><td bgcolor=\"#9cff83\">%2</td><td></td><td></td></tr>" ) 00086 .arg( name ) 00087 .arg( textToHTML( leftValue ) ) ); 00088 break; 00089 case AdditionalRightMode: 00090 mContent.append( QString::fromLatin1( "<tr><td align=\"right\"><b>%1:</b></td><td></td><td></td><td bgcolor=\"#9cff83\">%2</td></tr>" ) 00091 .arg( name ) 00092 .arg( textToHTML( rightValue ) ) ); 00093 break; 00094 } 00095 } 00096 00097 private: 00098 QString header() const 00099 { 00100 QString header = QLatin1String( "<html>" ); 00101 header += QString::fromLatin1( "<body text=\"%1\" bgcolor=\"%2\">" ) 00102 .arg( KColorScheme( QPalette::Active, KColorScheme::View ).foreground().color().name() ) 00103 .arg( KColorScheme( QPalette::Active, KColorScheme::View ).background().color().name() ); 00104 header += QLatin1String( "<center><table>" ); 00105 header += QString::fromLatin1( "<tr><th align=\"center\">%1</th><th align=\"center\">%2</th><td> </td><th align=\"center\">%3</th></tr>" ) 00106 .arg( mNameTitle ) 00107 .arg( mLeftTitle ) 00108 .arg( mRightTitle ); 00109 00110 return header; 00111 } 00112 00113 QString footer() const 00114 { 00115 return QLatin1String( "</table></center>" 00116 "</body>" 00117 "</html>" ); 00118 } 00119 00120 QString mContent; 00121 QString mNameTitle; 00122 QString mLeftTitle; 00123 QString mRightTitle; 00124 }; 00125 00126 static void compareItems( AbstractDifferencesReporter *reporter, const Akonadi::Item &localItem, const Akonadi::Item &otherItem ) 00127 { 00128 if ( localItem.modificationTime() != otherItem.modificationTime() ) { 00129 reporter->addProperty( AbstractDifferencesReporter::ConflictMode, i18n( "Modification Time" ), 00130 KGlobal::locale()->formatDateTime( localItem.modificationTime(), KLocale::ShortDate, true ), 00131 KGlobal::locale()->formatDateTime( otherItem.modificationTime(), KLocale::ShortDate, true ) ); 00132 } 00133 00134 if ( localItem.flags() != otherItem.flags() ) { 00135 QStringList localFlags; 00136 foreach ( const QByteArray &localFlag, localItem.flags() ) 00137 localFlags.append( QString::fromUtf8( localFlag ) ); 00138 00139 QStringList otherFlags; 00140 foreach ( const QByteArray &otherFlag, otherItem.flags() ) 00141 otherFlags.append( QString::fromUtf8( otherFlag ) ); 00142 00143 reporter->addProperty( AbstractDifferencesReporter::ConflictMode, i18n( "Flags" ), 00144 localFlags.join( QLatin1String( ", " ) ), 00145 otherFlags.join( QLatin1String( ", " ) ) ); 00146 } 00147 00148 QHash<QByteArray, QByteArray> localAttributes; 00149 foreach ( Akonadi::Attribute *attribute, localItem.attributes() ) { 00150 localAttributes.insert( attribute->type(), attribute->serialized() ); 00151 } 00152 00153 QHash<QByteArray, QByteArray> otherAttributes; 00154 foreach ( Akonadi::Attribute *attribute, otherItem.attributes() ) { 00155 otherAttributes.insert( attribute->type(), attribute->serialized() ); 00156 } 00157 00158 if ( localAttributes != otherAttributes ) { 00159 foreach ( const QByteArray &localKey, localAttributes.keys() ) { 00160 if ( !otherAttributes.contains( localKey ) ) { 00161 reporter->addProperty( AbstractDifferencesReporter::AdditionalLeftMode, i18n( "Attribute: %1", QString::fromUtf8( localKey ) ), 00162 QString::fromUtf8( localAttributes.value( localKey ) ), 00163 QString() ); 00164 } else { 00165 const QByteArray localValue = localAttributes.value( localKey ); 00166 const QByteArray otherValue = otherAttributes.value( localKey ); 00167 if ( localValue != otherValue ) { 00168 reporter->addProperty( AbstractDifferencesReporter::ConflictMode, i18n( "Attribute: %1", QString::fromUtf8( localKey ) ), 00169 QString::fromUtf8( localValue ), 00170 QString::fromUtf8( otherValue ) ); 00171 } 00172 } 00173 } 00174 00175 foreach ( const QByteArray &otherKey, otherAttributes.keys() ) { 00176 if ( !localAttributes.contains( otherKey ) ) { 00177 reporter->addProperty( AbstractDifferencesReporter::AdditionalRightMode, i18n( "Attribute: %1", QString::fromUtf8( otherKey ) ), 00178 QString(), 00179 QString::fromUtf8( otherAttributes.value( otherKey ) ) ); 00180 } 00181 } 00182 } 00183 } 00184 00185 ConflictResolveDialog::ConflictResolveDialog( QWidget *parent ) 00186 : KDialog( parent ), mResolveStrategy( ConflictHandler::UseBothItems ) 00187 { 00188 setCaption( i18nc( "@title:window", "Conflict Resolution" ) ); 00189 setButtons( User1 | User2 | User3 ); 00190 setDefaultButton( User3 ); 00191 00192 button( User3 )->setText( i18n( "Take left one" ) ); 00193 button( User2 )->setText( i18n( "Take right one" ) ); 00194 button( User1 )->setText( i18n( "Keep both" ) ); 00195 00196 connect( this, SIGNAL( user1Clicked() ), SLOT( slotUseBothItemsChoosen() ) ); 00197 connect( this, SIGNAL( user2Clicked() ), SLOT( slotUseOtherItemChoosen() ) ); 00198 connect( this, SIGNAL( user3Clicked() ), SLOT( slotUseLocalItemChoosen() ) ); 00199 00200 QWidget *mainWidget = new QWidget; 00201 QVBoxLayout *layout = new QVBoxLayout( mainWidget ); 00202 00203 QLabel* label = new QLabel( i18nc( "@label", "Two updates conflict with each other.<nl/>Please choose which update(s) to apply." ), mainWidget ); 00204 layout->addWidget( label ); 00205 00206 mView = new KTextBrowser; 00207 00208 layout->addWidget( mView ); 00209 00210 setMainWidget( mainWidget ); 00211 } 00212 00213 void ConflictResolveDialog::setConflictingItems( const Akonadi::Item &localItem, const Akonadi::Item &otherItem ) 00214 { 00215 mLocalItem = localItem; 00216 mOtherItem = otherItem; 00217 00218 HtmlDifferencesReporter reporter; 00219 00220 if ( mLocalItem.hasPayload() && mOtherItem.hasPayload() ) { 00221 00222 QObject *object = TypePluginLoader::objectForMimeTypeAndClass( localItem.mimeType(), localItem.availablePayloadMetaTypeIds() ); 00223 if ( object ) { 00224 DifferencesAlgorithmInterface *algorithm = qobject_cast<DifferencesAlgorithmInterface*>( object ); 00225 if ( algorithm ) { 00226 algorithm->compare( &reporter, localItem, otherItem ); 00227 mView->setHtml( reporter.toHtml() ); 00228 return; 00229 } 00230 } 00231 00232 reporter.addProperty( HtmlDifferencesReporter::NormalMode, i18n( "Data" ), 00233 QString::fromUtf8( mLocalItem.payloadData() ), 00234 QString::fromUtf8( mOtherItem.payloadData() ) ); 00235 } 00236 00237 compareItems( &reporter, localItem, otherItem ); 00238 00239 mView->setHtml( reporter.toHtml() ); 00240 } 00241 00242 ConflictHandler::ResolveStrategy ConflictResolveDialog::resolveStrategy() const 00243 { 00244 return mResolveStrategy; 00245 } 00246 00247 void ConflictResolveDialog::slotUseLocalItemChoosen() 00248 { 00249 mResolveStrategy = ConflictHandler::UseLocalItem; 00250 accept(); 00251 } 00252 00253 void ConflictResolveDialog::slotUseOtherItemChoosen() 00254 { 00255 mResolveStrategy = ConflictHandler::UseOtherItem; 00256 accept(); 00257 } 00258 00259 void ConflictResolveDialog::slotUseBothItemsChoosen() 00260 { 00261 mResolveStrategy = ConflictHandler::UseBothItems; 00262 accept(); 00263 } 00264 00265 #include "conflictresolvedialog_p.moc"