1 /***************************************************************************
2 * Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 ***************************************************************************/
10 #include "propertiesdialog.h"
16 #include <qheaderview.h>
18 #include <qprogressbar.h>
19 #include <qsortfilterproxymodel.h>
20 #include <qtreeview.h>
22 #include <kfiledialog.h>
25 #include <kmessagebox.h>
26 #include <ksqueezedtextlabel.h>
27 #include <kglobalsettings.h>
30 #include "core/document.h"
31 #include "core/fontinfo.h"
33 static const int IsExtractableRole
= Qt::UserRole
;
34 static const int FontInfoRole
= Qt::UserRole
+ 1;
36 PropertiesDialog::PropertiesDialog(QWidget
*parent
, Okular::Document
*doc
)
37 : KPageDialog( parent
), m_document( doc
), m_fontPage( 0 ),
38 m_fontModel( 0 ), m_fontInfo( 0 ), m_fontProgressBar( 0 ),
39 m_fontScanStarted( false )
41 setFaceType( Tabbed
);
42 setCaption( i18n( "Unknown File" ) );
46 QFrame
*page
= new QFrame();
47 KPageWidgetItem
*item
= addPage( page
, i18n( "&Properties" ) );
48 item
->setIcon( KIcon( "document-properties" ) );
49 QGridLayout
*layout
= new QGridLayout( page
);
50 layout
->setMargin( marginHint() );
51 layout
->setSpacing( spacingHint() );
53 // get document info, if not present display blank data and a warning
54 const Okular::DocumentInfo
* info
= doc
->documentInfo();
56 layout
->addWidget( new QLabel( i18n( "No document opened." ), page
), 0, 0 );
60 // mime name based on mimetype id
61 QString mimeName
= info
->get( "mimeType" ).section( '/', -1 ).toUpper();
62 setCaption( i18n( "%1 Properties", mimeName
) );
64 QDomElement docElement
= info
->documentElement();
67 int valMaxWidth
= 100;
68 for ( QDomNode node
= docElement
.firstChild(); !node
.isNull(); node
= node
.nextSibling() ) {
69 QDomElement element
= node
.toElement();
71 QString titleString
= element
.attribute( "title" );
72 QString valueString
= element
.attribute( "value" );
73 if ( titleString
.isEmpty() || valueString
.isEmpty() )
76 // create labels and layout them
77 QLabel
*key
= new QLabel( i18n( "%1:", titleString
), page
);
78 QLabel
*value
= new KSqueezedTextLabel( valueString
, page
);
79 value
->setTextInteractionFlags( Qt::TextSelectableByMouse
);
80 layout
->addWidget( key
, row
, 0, Qt::AlignRight
);
81 layout
->addWidget( value
, row
, 1 );
84 // refine maximum width of 'value' labels
85 valMaxWidth
= qMax( valMaxWidth
, fontMetrics().width( valueString
) );
88 // add the number of pages if the generator hasn't done it already
89 QDomNodeList list
= docElement
.elementsByTagName( "pages" );
90 if ( list
.count() == 0 ) {
91 QLabel
*key
= new QLabel( i18n( "Pages:" ), page
);
92 QLabel
*value
= new QLabel( QString::number( doc
->pages() ), page
);
93 value
->setTextInteractionFlags( Qt::TextSelectableByMouse
);
95 layout
->addWidget( key
, row
, 0, Qt::AlignRight
);
96 layout
->addWidget( value
, row
, 1 );
100 QVBoxLayout
*page2Layout
= 0;
101 if ( doc
->canProvideFontInformation() ) {
102 // create fonts tab and layout it
103 QFrame
*page2
= new QFrame();
104 m_fontPage
= addPage(page2
, i18n("&Fonts"));
105 m_fontPage
->setIcon( KIcon( "preferences-desktop-font" ) );
106 page2Layout
= new QVBoxLayout(page2
);
107 page2Layout
->setMargin(marginHint());
108 page2Layout
->setSpacing(spacingHint());
110 QTreeView
*view
= new QTreeView(page2
);
111 view
->setContextMenuPolicy(Qt::CustomContextMenu
);
112 connect(view
, SIGNAL(customContextMenuRequested(const QPoint
&)), this, SLOT(showFontsMenu(const QPoint
&)));
113 page2Layout
->addWidget(view
);
114 view
->setRootIsDecorated(false);
115 view
->setAlternatingRowColors(true);
116 view
->setSortingEnabled( true );
117 // creating a proxy model so we can sort the data
118 QSortFilterProxyModel
*proxymodel
= new QSortFilterProxyModel(view
);
119 proxymodel
->setDynamicSortFilter( true );
120 proxymodel
->setSortCaseSensitivity( Qt::CaseInsensitive
);
121 m_fontModel
= new FontsListModel(view
);
122 proxymodel
->setSourceModel(m_fontModel
);
123 view
->setModel(proxymodel
);
124 view
->sortByColumn( 0, Qt::AscendingOrder
);
125 m_fontInfo
= new QLabel( this );
126 page2Layout
->addWidget( m_fontInfo
);
127 m_fontInfo
->setText( i18n( "Reading font information..." ) );
129 m_fontProgressBar
= new QProgressBar( this );
130 page2Layout
->addWidget( m_fontProgressBar
);
131 m_fontProgressBar
->setRange( 0, 100 );
132 m_fontProgressBar
->setValue( 0 );
133 m_fontProgressBar
->hide();
136 // current width: left columnt + right column + dialog borders
137 int width
= layout
->minimumSize().width() + valMaxWidth
+ 2 * marginHint() + spacingHint() + 30;
139 width
= qMax( width
, page2Layout
->sizeHint().width() + marginHint() + spacingHint() + 31 );
140 // stay inside the 2/3 of the screen width
141 QRect screenContainer
= KGlobalSettings::desktopGeometry( this );
142 width
= qMin( width
, 2*screenContainer
.width()/3 );
145 connect( pageWidget(), SIGNAL( currentPageChanged( KPageWidgetItem
*, KPageWidgetItem
* ) ),
146 this, SLOT( pageChanged( KPageWidgetItem
*, KPageWidgetItem
* ) ) );
149 PropertiesDialog::~PropertiesDialog()
151 m_document
->stopFontReading();
154 void PropertiesDialog::pageChanged( KPageWidgetItem
*current
, KPageWidgetItem
* )
156 if ( current
== m_fontPage
&& !m_fontScanStarted
)
158 connect( m_document
, SIGNAL( gotFont( const Okular::FontInfo
& ) ), m_fontModel
, SLOT( addFont( const Okular::FontInfo
& ) ) );
159 connect( m_document
, SIGNAL( fontReadingProgress( int ) ), this, SLOT( slotFontReadingProgress( int ) ) );
160 connect( m_document
, SIGNAL( fontReadingEnded() ), this, SLOT( slotFontReadingEnded() ) );
161 QTimer::singleShot( 0, this, SLOT( reallyStartFontReading() ) );
163 m_fontScanStarted
= true;
167 void PropertiesDialog::slotFontReadingProgress( int page
)
169 m_fontProgressBar
->setValue( m_fontProgressBar
->maximum() * ( page
+ 1 ) / m_document
->pages() );
172 void PropertiesDialog::slotFontReadingEnded()
175 m_fontProgressBar
->hide();
178 void PropertiesDialog::reallyStartFontReading()
181 m_fontProgressBar
->show();
182 m_document
->startFontReading();
185 void PropertiesDialog::showFontsMenu(const QPoint
&pos
)
187 QTreeView
*view
= static_cast<QTreeView
*>(sender());
188 QModelIndex index
= view
->indexAt(pos
);
189 if (index
.data(IsExtractableRole
).toBool())
191 QMenu
*menu
= new QMenu(this);
192 menu
->addAction( i18nc("@action:inmenu", "&Extract Font") );
193 QAction
*result
= menu
->exec(view
->viewport()->mapToGlobal(pos
));
196 Okular::FontInfo fi
= index
.data(FontInfoRole
).value
<Okular::FontInfo
>();
197 const QString caption
= i18n( "Where do you want to save %1?", fi
.name() );
198 const QString path
= KFileDialog::getSaveFileName( fi
.name(), QString(), this, caption
);
199 if ( path
.isEmpty() )
203 if ( !f
.exists() || KMessageBox::warningContinueCancel( this, i18n( "A file named \"%1\" already exists. Are you sure you want to overwrite it?", path
), QString(), KGuiItem( i18nc( "@action:button", "&Overwrite" ) ) ) == KMessageBox::Continue
)
205 if ( f
.open( QIODevice::WriteOnly
) )
207 f
.write( m_document
->fontData(fi
) );
212 KMessageBox::error( this, i18n( "Could not open \"%1\" for writing. File was not saved.", path
) );
219 FontsListModel::FontsListModel( QObject
* parent
)
220 : QAbstractTableModel( parent
)
224 FontsListModel::~FontsListModel()
228 void FontsListModel::addFont( const Okular::FontInfo
&fi
)
230 beginInsertRows( QModelIndex(), m_fonts
.size(), m_fonts
.size() );
237 int FontsListModel::columnCount( const QModelIndex
&parent
) const
239 return parent
.isValid() ? 0 : 3;
242 static QString
descriptionForFontType( Okular::FontInfo::FontType type
)
246 case Okular::FontInfo::Type1
:
247 return i18n("Type 1");
249 case Okular::FontInfo::Type1C
:
250 return i18n("Type 1C");
252 case Okular::FontInfo::Type1COT
:
253 return i18nc("OT means OpenType", "Type 1C (OT)");
255 case Okular::FontInfo::Type3
:
256 return i18n("Type 3");
258 case Okular::FontInfo::TrueType
:
259 return i18n("TrueType");
261 case Okular::FontInfo::TrueTypeOT
:
262 return i18nc("OT means OpenType", "TrueType (OT)");
264 case Okular::FontInfo::CIDType0
:
265 return i18n("CID Type 0");
267 case Okular::FontInfo::CIDType0C
:
268 return i18n("CID Type 0C");
270 case Okular::FontInfo::CIDType0COT
:
271 return i18nc("OT means OpenType", "CID Type 0C (OT)");
273 case Okular::FontInfo::CIDTrueType
:
274 return i18n("CID TrueType");
276 case Okular::FontInfo::CIDTrueTypeOT
:
277 return i18nc("OT means OpenType", "CID TrueType (OT)");
279 case Okular::FontInfo::Unknown
:
280 return i18nc("Unknown font type", "Unknown");
286 static QString
pathOrDescription( const Okular::FontInfo
&font
)
288 switch ( font
.embedType() )
290 case Okular::FontInfo::NotEmbedded
:
293 case Okular::FontInfo::EmbeddedSubset
:
294 return i18n("Embedded (subset)");
296 case Okular::FontInfo::FullyEmbedded
:
297 return i18n("Fully embedded");
303 static QString
descriptionForEmbedType( Okular::FontInfo::EmbedType type
)
307 case Okular::FontInfo::NotEmbedded
:
310 case Okular::FontInfo::EmbeddedSubset
:
311 return i18n("Yes (subset)");
313 case Okular::FontInfo::FullyEmbedded
:
320 QVariant
FontsListModel::data( const QModelIndex
&index
, int role
) const
322 if ( !index
.isValid() || index
.row() < 0 || index
.row() >= m_fonts
.count() )
327 case Qt::DisplayRole
:
328 switch ( index
.column() )
332 QString fontname
= m_fonts
.at( index
.row() ).name();
333 return fontname
.isEmpty() ? i18nc( "font name not available (empty)", "[n/a]" ) : fontname
;
337 return descriptionForFontType( m_fonts
.at( index
.row() ).type() );
340 return pathOrDescription( m_fonts
.at( index
.row() ) );
344 case Qt::ToolTipRole
:
346 QString fontname
= m_fonts
.at( index
.row() ).name();
347 if ( fontname
.isEmpty() )
348 fontname
= i18n( "Unknown font" );
349 QString tooltip
= QString::fromLatin1( "<html><b>" ) + fontname
+ QString::fromLatin1( "</b>" );
350 if ( m_fonts
.at( index
.row() ).embedType() == Okular::FontInfo::NotEmbedded
)
351 tooltip
+= QString::fromLatin1( " (<span style=\"font-family: '%1'\">%2</span>)" ).arg( fontname
).arg( fontname
);
352 tooltip
+= QString::fromLatin1( "<br />" ) + i18n( "Embedded: %1", descriptionForEmbedType( m_fonts
.at( index
.row() ).embedType() ) );
353 tooltip
+= QString::fromLatin1( "</html>" );
357 case IsExtractableRole
:
359 return m_fonts
.at( index
.row() ).canBeExtracted();
364 v
.setValue( m_fonts
.at( index
.row() ) );
372 QVariant
FontsListModel::headerData( int section
, Qt::Orientation orientation
, int role
) const
374 if ( orientation
!= Qt::Horizontal
)
377 if ( role
== Qt::TextAlignmentRole
)
378 return QVariant( Qt::AlignLeft
);
380 if ( role
!= Qt::DisplayRole
)
385 case 0: return i18n( "Name" ); break;
386 case 1: return i18n( "Type" ); break;
387 case 2: return i18n( "File" ); break;
393 int FontsListModel::rowCount( const QModelIndex
&parent
) const
395 return parent
.isValid() ? 0 : m_fonts
.size();
398 #include "propertiesdialog.moc"
400 /* kate: replace-tabs on; indent-width 4; */