1 /* -*- mode: C++; c-file-style: "gnu" -*-
3 * This file is part of KMail, the KDE mail client.
5 * Copyright (c) 2002-2003 Carsten Pfeiffer <pfeiffer@kde.org>
6 * Copyright (c) 2003 Zack Rusin <zack@kde.org>
8 * KMail is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License, version 2, as
10 * published by the Free Software Foundation.
12 * KMail is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * In addition, as a special exception, the copyright holders give
22 * permission to link the code of this program with any edition of
23 * the Qt library by Trolltech AS, Norway (or with modified versions
24 * of Qt that use the same license as Qt), and distribute linked
25 * combinations including the two. You must obey the GNU General
26 * Public License in all respects for all of the code used other than
27 * Qt. If you modify this file, you may extend this exception to
28 * your version of the file, but you are not obligated to do so. If
29 * you do not wish to do so, delete this exception statement from
32 #include <config-messageviewer.h>
34 #include "mailsourceviewer.h"
35 #include "findbar/findbarsourceview.h"
36 #include <kiconloader.h>
37 #include <KLocalizedString>
38 #include <kstandardguiitem.h>
39 #include <kwindowsystem.h>
41 #include <QtCore/QRegExp>
42 #include <QtGui/QApplication>
43 #include <QtGui/QIcon>
44 #include <QtGui/QPushButton>
45 #include <QtGui/QShortcut>
46 #include <QtGui/QTabBar>
47 #include <QtGui/QVBoxLayout>
49 namespace MessageViewer
{
51 void MailSourceHighlighter::highlightBlock ( const QString
& text
) {
52 // all visible ascii except space and :
53 const QRegExp
regexp( "^([\\x21-9;-\\x7E]+:\\s)" );
54 const int headersState
= -1; // Also the initial State
55 const int bodyState
= 0;
57 // keep the previous state
58 setCurrentBlockState( previousBlockState() );
59 // If a header is found
60 if( regexp
.indexIn( text
) != -1 )
62 // Content- header starts a new mime part, and therefore new headers
63 // If a Content-* header is found, change State to headers until a blank line is found.
64 if ( text
.startsWith( QLatin1String( "Content-" ) ) )
66 setCurrentBlockState( headersState
);
68 // highligth it if in headers state
69 if( ( currentBlockState() == headersState
) )
71 QFont font
= document()->defaultFont ();
73 setFormat( 0, regexp
.matchedLength(), font
);
76 // Change to body state
77 else if ( text
.isEmpty() )
79 setCurrentBlockState( bodyState
);
83 void HTMLSourceHighlighter::highlightBlock ( const QString
& text
) {
85 if( ( pos
= HTMLPrettyFormatter::htmlTagRegExp
.indexIn( text
) ) != -1 )
87 QFont font
= document()->defaultFont();
89 setFormat( pos
, HTMLPrettyFormatter::htmlTagRegExp
.matchedLength(), font
);
93 const QString
HTMLPrettyFormatter::reformat( const QString
&src
)
95 const QRegExp
cleanLeadingWhitespace( "(?:\\n)+\\w*" );
96 QStringList tmpSource
;
97 QString
source( src
);
101 //First make sure that each tag is surrounded by newlines
102 while( (pos
= htmlTagRegExp
.indexIn( source
, pos
) ) != -1 )
104 source
.insert(pos
, '\n');
105 pos
+= htmlTagRegExp
.matchedLength() + 1;
106 source
.insert(pos
, '\n');
110 // Then split the source on newlines skiping empty parts.
111 // Now a line is either a tag or pure data.
112 tmpSource
= source
.split('\n', QString::SkipEmptyParts
);
114 // Then clean any leading whitespace
115 for( int i
= 0; i
!= tmpSource
.length(); i
++ )
117 tmpSource
[i
] = tmpSource
[i
].remove( cleanLeadingWhitespace
);
120 // Then indent as appropriate
121 for( int i
= 0; i
!= tmpSource
.length(); i
++ ) {
122 if( htmlTagRegExp
.indexIn( tmpSource
[i
] ) != -1 ) // A tag
124 if( htmlTagRegExp
.cap( 3 ) == "/" || htmlTagRegExp
.cap( 2 ) == "img" || htmlTagRegExp
.cap( 2 ) == "br" ) {
125 //Self closing tag or no closure needed
128 if( htmlTagRegExp
.cap( 1 ) == "/" ) {
131 tmpSource
[i
].prepend( indent
);
135 tmpSource
[i
].prepend( indent
);
136 indent
.append( " " );
140 tmpSource
[i
].prepend( indent
);
143 // Finally reassemble and return :)
144 return tmpSource
.join( "\n" );
147 MailSourceViewer::MailSourceViewer( QWidget
*parent
)
148 : KDialog( parent
), mRawSourceHighLighter( 0 )
150 setAttribute( Qt::WA_DeleteOnClose
);
153 QVBoxLayout
*layout
= new QVBoxLayout( mainWidget() );
154 layout
->setMargin( 0 );
155 mTabWidget
= new KTabWidget
;
156 layout
->addWidget( mTabWidget
);
158 connect( this, SIGNAL(closeClicked()), SLOT(close()) );
161 QWidget
*widget
= new QWidget
;
162 QVBoxLayout
*lay
= new QVBoxLayout
;
163 widget
->setLayout( lay
);
164 mRawBrowser
= new KTextBrowser();
165 lay
->addWidget( mRawBrowser
);
166 mFindBar
= new FindBarSourceView( mRawBrowser
, widget
);
167 lay
->addWidget( mFindBar
);
168 mTabWidget
->addTab( /*mRawBrowser*/widget
, i18nc( "Unchanged mail message", "Raw Source" ) );
169 mTabWidget
->setTabToolTip( 0, i18n( "Raw, unmodified mail as it is stored on the filesystem or on the server" ) );
170 mRawBrowser
->setLineWrapMode( QTextEdit::NoWrap
);
171 mRawBrowser
->setTextInteractionFlags( Qt::TextSelectableByMouse
| Qt::TextSelectableByKeyboard
);
174 mHtmlBrowser
= new KTextBrowser();
175 mTabWidget
->addTab( mHtmlBrowser
, i18nc( "Mail message as shown, in HTML format", "HTML Source" ) );
176 mTabWidget
->setTabToolTip( 1, i18n( "HTML code for displaying the message to the user" ) );
177 mHtmlBrowser
->setLineWrapMode( QTextEdit::NoWrap
);
178 mHtmlBrowser
->setTextInteractionFlags( Qt::TextSelectableByMouse
| Qt::TextSelectableByKeyboard
);
179 mHtmlSourceHighLighter
= new HTMLSourceHighlighter( mHtmlBrowser
);
182 mTabWidget
->setCurrentIndex( 0 );
184 // combining the shortcuts in one qkeysequence() did not work...
185 QShortcut
* shortcut
= new QShortcut( this );
186 shortcut
->setKey( Qt::Key_Escape
);
187 connect( shortcut
, SIGNAL(activated()), SLOT(close()) );
189 shortcut
= new QShortcut( this );
190 shortcut
->setKey( Qt::Key_W
+Qt::CTRL
);
191 connect( shortcut
, SIGNAL(activated()), SLOT(close()) );
193 shortcut
= new QShortcut( this );
194 shortcut
->setKey( Qt::Key_F
+Qt::CTRL
);
195 connect( shortcut
, SIGNAL(activated()), SLOT(slotFind()) );
197 KWindowSystem::setIcons( winId(),
198 qApp
->windowIcon().pixmap( IconSize( KIconLoader::Desktop
),
199 IconSize( KIconLoader::Desktop
) ),
200 qApp
->windowIcon().pixmap( IconSize( KIconLoader::Small
),
201 IconSize( KIconLoader::Small
) ) );
202 mRawSourceHighLighter
= new MailSourceHighlighter( mRawBrowser
);
205 MailSourceViewer::~MailSourceViewer()
209 void MailSourceViewer::setRawSource( const QString
&source
)
211 mRawBrowser
->setText( source
);
214 void MailSourceViewer::setDisplayedSource( const QString
&source
)
217 mHtmlBrowser
->setPlainText( HTMLPrettyFormatter::reformat( source
) );
223 void MailSourceViewer::slotFind()
226 mFindBar
->focusAndSetCursor();
229 #include "mailsourceviewer.moc"