1 /***************************************************************************
3 copyright : (C) 2003, 2004, 2005, 2006 by Carsten Niehaus
4 email : cniehaus@kde.org
5 ***************************************************************************/
7 /***************************************************************************
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
14 ***************************************************************************/
16 #include "detailinfodlg.h"
18 #include "kalziumdataobject.h"
21 #include <khtml_part.h>
22 #include <dom/html_base.h>
23 #include <dom/html_document.h>
24 #include <khtmlview.h>
25 #include <kstandarddirs.h>
26 #include <kactioncollection.h>
27 #include <kpagewidgetmodel.h>
28 #include <ktoolinvocation.h>
35 #include <QPushButton>
36 #include <QStackedWidget>
40 #include "orbitswidget.h"
41 #include "detailedgraphicaloverview.h"
42 #include "spectrumviewimpl.h"
43 #include "kalziumutils.h"
44 #include "kalziumtabletype.h"
46 DetailedInfoDlg::DetailedInfoDlg( int el
, QWidget
*parent
)
47 : KPageDialog( parent
), m_ktt( 0 )
50 setButtons( Help
| User1
| User2
| Close
);
51 setDefaultButton( Close
);
52 setButtonGuiItem( User1
, KGuiItem( i18nc( "Next element", "Next" ),
53 ( layoutDirection() == Qt::LeftToRight
) ? "arrow-right" : "arrow-left", i18n( "Goes to the next element" ) ) );
54 setButtonGuiItem( User2
, KGuiItem( i18nc( "Previous element", "Previous" ),
55 ( layoutDirection() == Qt::LeftToRight
) ? "arrow-left" : "arrow-right", i18n( "Goes to the previous element" ) ) );
57 m_baseHtml
= KGlobal::dirs()->findResourceDir( "appdata", "data/" ) + "data/htmlview/";
58 m_baseHtml2
= KGlobal::dirs()->findResourceDir( "appdata", "data/" ) + "data/hazardsymbols/";
60 //X m_picsdir = KGlobal::dirs()->findResourceDir( "appdata", "elempics/" ) + "elempics/";
62 // creating the tabs but not the contents, as that will be done when setting the element
65 m_actionCollection
= new KActionCollection(this);
66 KStandardAction::quit(this, SLOT(close()), m_actionCollection
);
68 connect( this, SIGNAL( user1Clicked() ), this, SLOT( slotUser1() ) );
69 connect( this, SIGNAL( user2Clicked() ), this, SLOT( slotUser2() ) );
70 connect( this, SIGNAL( helpClicked() ), this, SLOT( slotHelp() ) );
72 // setting the element and updating the whole dialog
76 void DetailedInfoDlg::setElement( int el
)
78 Element
*element
= KalziumDataObject::instance()->element( el
);
79 if ( !element
) return;
84 emit
elementChanged( m_elementNumber
);
88 enableButton( User1
, true );
89 enableButton( User2
, true );
90 if ( m_elementNumber
== 1 )
91 enableButton( User2
, false );
92 else if ( m_elementNumber
== KalziumDataObject::instance()->numberOfElements() )
93 enableButton( User1
, false );
96 void DetailedInfoDlg::setOverviewBackgroundColor( const QColor
&bgColor
)
98 dTab
->setBackgroundColor( bgColor
);
101 void DetailedInfoDlg::setTableType( KalziumTableType
* ktt
)
106 KHTMLPart
* DetailedInfoDlg::addHTMLTab( const QString
& title
, const QString
& icontext
, const QString
& iconname
)
108 QWidget
* frame
= new QWidget();
109 KPageWidgetItem
*item
= addPage( frame
, title
);
110 item
->setHeader( icontext
);
111 item
->setIcon( KIcon( iconname
) );
112 QVBoxLayout
*layout
= new QVBoxLayout( frame
);
113 layout
->setMargin( 0 );
114 KHTMLPart
*w
= new KHTMLPart( frame
, frame
);
115 layout
->addWidget( w
->view() );
120 void DetailedInfoDlg::fillHTMLTab( KHTMLPart
* htmlpart
, const QString
& htmlcode
)
122 if ( !htmlpart
) return;
125 htmlpart
->write( htmlcode
);
127 // set the background color of the document to match that of the dialog
128 DOM::HTMLElement element
= htmlpart
->htmlDocument().body();
129 if ( element
.tagName() == "body" )
131 const QColor backgroundColor
= palette().background().color();
132 ((DOM::HTMLBodyElement
)element
).setBgColor( backgroundColor
.name() );
138 QString
DetailedInfoDlg::getHtml( DATATYPE type
)
142 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"
143 "<html><head><title>Chemical data</title>"
144 "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + m_baseHtml
+ "style.css\" />"
145 "<base href=\"" + m_baseHtml
+ "\"/></head><body>"
146 "<div class=\"chemdata\"><div><table summary=\"header\">"
147 "<tr><td>" + m_element
->dataAsString( ChemicalDataObject::symbol
) + "<td><td>"
148 + i18n( "Block: %1", m_element
->dataAsString( ChemicalDataObject::periodTableBlock
) ) +
149 "</td></tr></table></div>"
150 "<table summary=\"characteristics\" class=\"characterstics\">";
156 // discovery date and discoverers
157 html
.append( "<tr><td><img src=\"discovery.png\" alt=\"icon\"/></td><td>" );
158 html
+= KalziumUtils::prettyUnit( m_element
, ChemicalDataObject::date
);
159 QString discoverers
= m_element
->dataAsString( ChemicalDataObject::discoverers
);
160 if ( !discoverers
.isEmpty() )
162 discoverers
= discoverers
.replace( ";", ", " );
163 html
+= "<br />" + i18n( "It was discovered by %1.", discoverers
);
165 html
.append( "</td></tr>" );
166 // origin of the name
167 QString nameorigin
= m_element
->dataAsString( ChemicalDataObject::nameOrigin
);
168 if ( !nameorigin
.isEmpty() )
170 html
.append( "<tr><td><img src=\"book.png\" alt=\"icon\"/></td><td>" );
171 html
.append( i18n( "Origin of the name:<br/>%1", nameorigin
) );
172 html
.append( "</td></tr>" );
174 //X if ( m_element->artificial() || m_element->radioactive() )
176 //X html.append( "<tr><td><img src=\"structure.png\" alt=\"icon\"/></td><td>" );
177 //X if ( !m_element->radioactive() )
178 //X html.append( i18n( "This element is artificial" ));
179 //X else if ( !m_element->artificial() )
180 //X html.append( i18n( "This element is radioactive" ));
182 //X html.append( i18n( "This element is radioactive and artificial" ));
183 //X html.append( "</td></tr>" );
189 html
.append( "<tr><td>" );
190 html
.append( isotopeTable() );
191 html
.append( "</td></tr>" );
197 html
.append( "<tr><td><img src=\"meltingpoint.png\" alt=\"icon\"/></td><td>" );
198 html
.append( i18n( "Melting Point: %1", KalziumUtils::prettyUnit( m_element
, ChemicalDataObject::meltingpoint
) ) );
199 html
.append( "</td></tr>" );
202 html
.append( "<tr><td><img src=\"boilingpoint.png\" alt=\"icon\"/></td><td>" );
203 html
.append( i18n( "Boiling Point: %1", KalziumUtils::prettyUnit( m_element
, ChemicalDataObject::boilingpoint
) ) );
204 html
.append( "</td></tr>" );
206 html
.append( "</table>" );
207 html
.append( "<table summary=\"characteristics\" class=\"characterstics\">" );
210 html
.append( "<tr><td><img src=\"electronaffinity.png\" alt=\"icon\"/></td><td>" );
211 html
.append( i18n( "Electron Affinity: %1", KalziumUtils::prettyUnit( m_element
, ChemicalDataObject::electronAffinity
) ) );
212 html
.append( "</td></tr>" );
214 //Electronic configuration
215 html
.append( "<tr><td><img src=\"structure.png\" alt=\"icon\"/></td><td>" );
216 //Probably beautify here...
217 QString config
= beautifyOrbitalString(m_element
->dataAsString( ChemicalDataObject::electronicConfiguration
) );
218 html
.append( i18n( "Electronic configuration: %1", config
) );
219 html
.append( "</td></tr>" );
222 html
.append( "<tr><td><img src=\"radius.png\" alt=\"icon\"/></td><td>" );
223 html
.append( i18n( "Covalent Radius: %1", KalziumUtils::prettyUnit( m_element
, ChemicalDataObject::radiusCovalent
) ) );
224 html
.append( "</td></tr>" );
226 // van der Waals radius
227 html
.append( "<tr><td><img src=\"radius.png\" alt=\"icon\"/></td><td>" );
228 html
.append( i18n( "van der Waals Radius: %1", KalziumUtils::prettyUnit( m_element
, ChemicalDataObject::radiusVDW
) ) );
229 html
.append( "</td></tr>" );
232 html
.append( "<tr><td stype=\"text-align:center\"><img src=\"mass.png\" alt=\"icon\"/></td><td>" );
233 html
.append( i18n( "Mass: %1", KalziumUtils::prettyUnit( m_element
, ChemicalDataObject::mass
) ) );
234 html
.append( "</td></tr>" );
236 // 1st ionization energy
237 html
.append( "<tr><td><img src=\"ionisation.png\" alt=\"icon\"/></td><td>" );
238 html
.append( i18n( "First Ionization energy: %1", KalziumUtils::prettyUnit( m_element
, ChemicalDataObject::ionization
) ) );
239 html
.append( "</td></tr>" );
241 // electro negativity
242 html
.append( "<tr><td><img src=\"structure.png\" alt=\"icon\"/></td><td>" );
243 html
.append( i18n( "Electronegativity: %1", KalziumUtils::prettyUnit( m_element
, ChemicalDataObject::electronegativityPauling
) ) );
244 html
.append( "</td></tr>" );
248 html
+= "</table></div></body></html>";
253 QString
DetailedInfoDlg::isotopeTable() const
255 QList
<Isotope
*> list
= KalziumDataObject::instance()->isotopes( m_elementNumber
);
259 html
= "<table class=\"isotopes\" cellspacing=\"0\"><tr><td colspan=\"7\">";
260 html
+= i18n( "Isotope-Table" );
261 html
+= "</tr></td><tr><td><b>";
262 html
+= i18n( "Mass" );
263 html
+= "</b></td><td><b>";
264 html
+= i18n( "Neutrons" );
265 html
+= "</b></td><td><b>";
266 html
+= i18n( "Percentage" );
267 html
+= "</b></td><td><b>";
268 html
+= i18n( "Half-life period" );
269 html
+= "</b></td><td><b>";
270 html
+= i18n( "Energy and Mode of Decay" );
271 html
+= "</b></td><td><b>";
272 html
+= i18n( "Spin and Parity" );
273 html
+= "</b></td><td><b>";
274 html
+= i18n( "Magnetic Moment" );
275 html
+= "</b></td></tr>";
277 foreach( Isotope
* isotope
, list
)
279 html
.append( "<tr><td align=\"right\">" );
280 if ( isotope
->mass() > 0.0 )
281 html
.append( i18n( "%1 u", isotope
->mass() ) );
282 html
.append( "</td><td>" );
283 html
.append( QString::number( (( isotope
)->nucleons()-( isotope
)->parentElementNumber()) ) );
284 html
.append( "</td><td>" );
285 if ( !( isotope
)->abundance().isEmpty() )
286 html
.append( i18nc( "this can for example be '24%'", "%1%", ( isotope
)->abundance() ) );
287 html
.append( "</td><td>" );
288 if ( ( isotope
)->halflife() > 0.0 )
289 html
.append( i18nc( "The first argument is the value, the second is the unit. For example '17 s' for '17 seconds',.", "%1 %2", ( isotope
)->halflife(), ( isotope
)->halflifeUnit( ) ) );
290 html
.append( "</td><td>" );
291 if ( ( isotope
)->alphalikeliness() > 0.0){
292 if ( ( isotope
)->alphadecay() > 0.0 )
293 html
.append( i18n( "%1 MeV", ( isotope
)->alphadecay() ));
294 html
.append( i18n( " %1", QChar( 945 ) ));
295 if ( ( isotope
)->alphalikeliness() < 100.0)
296 html
.append( i18n( "(%1%)", ( isotope
)->alphalikeliness()));
297 if ( ( isotope
)->betaminuslikeliness() > 0.0 || ( isotope
)->betapluslikeliness() > 0.0 || ( isotope
)->eclikeliness() > 0.0)
298 html
.append( i18n( ", " ) );
300 if ( ( isotope
)->betaminuslikeliness() > 0.0){
301 if ( ( isotope
)->betaminusdecay() > 0.0 )
302 html
.append( i18n( "%1 MeV", ( isotope
)->betaminusdecay() ));
303 html
.append( i18n( " %1<sup>-</sup>", QChar( 946 ) ));
304 if ( ( isotope
)->betaminuslikeliness() < 100.0)
305 html
.append( i18n( "(%1%)", ( isotope
)->betaminuslikeliness() ));
307 if ( ( isotope
)->betapluslikeliness() > 0.0 || ( isotope
)->eclikeliness() > 0.0 )
308 html
.append( i18n( ", " ) );
310 if ( ( isotope
)->betapluslikeliness() > 0.0) {
311 if ( ( isotope
)->betaplusdecay() > 0.0 )
312 html
.append( i18n( "%1 MeV", ( isotope
)->betaplusdecay() ));
313 html
.append( i18n( " %1<sup>+</sup>", QChar( 946 ) ));
314 if ( ( isotope
)->betapluslikeliness() == ( isotope
)->eclikeliness() ) {
315 if ( ( isotope
)->ecdecay() > 0.0 ) {
316 html
.append( i18n( "%1 MeV", ( isotope
)->ecdecay() )); }
317 html
.append( i18nc( "Acronym of Electron Capture"," EC" ) );
319 if ( ( isotope
)->betapluslikeliness() < 100.0)
320 html
.append( i18n( "(%1%)", ( isotope
)->betapluslikeliness() ));
323 if ( ( isotope
)->eclikeliness() > 0.0 ){
324 if ( ( isotope
)->ecdecay() > 0.0 )
325 html
.append( i18n( "%1 MeV", ( isotope
)->ecdecay() ));
326 html
.append( i18nc( "Acronym of Electron Capture"," EC" ) );
327 if ( ( isotope
)->eclikeliness() < 100.0 )
328 html
.append( i18n( "(%1%)", ( isotope
)->eclikeliness() ));
330 html
.append( "</td><td>" );
331 html
.append( ( isotope
)->spin() );
332 html
.append( "</td><td>" );
333 if ( !( isotope
)->magmoment().isEmpty() )
334 html
.append( i18n( "%1 %2<sub>n</sub>", ( isotope
)->magmoment(), QChar( 956 ) ) );
335 html
.append( "</td></tr>" );
344 void DetailedInfoDlg::createContent()
346 KPageWidgetItem
*item
= 0;
349 QWidget
*m_pOverviewTab
= new QWidget();
350 item
= addPage( m_pOverviewTab
, i18n( "Overview" ) );
351 item
->setHeader( i18n( "Overview" ) );
352 item
->setIcon( KIcon( "overview" ) );
353 QVBoxLayout
*overviewLayout
= new QVBoxLayout( m_pOverviewTab
);
354 overviewLayout
->setMargin( 0 );
355 dTab
= new DetailedGraphicalOverview( m_pOverviewTab
);
356 dTab
->setObjectName( "DetailedGraphicalOverview" );
357 overviewLayout
->addWidget( dTab
);
360 //X QWidget *m_pPictureTab = new QWidget();
361 //X item = addPage( m_pPictureTab, i18n( "Picture" ) );
362 //X item->setHeader( i18n( "What does this element look like?" ) );
363 //X item->setIcon( KIcon( "elempic" ) );
364 //X QVBoxLayout *mainLayout = new QVBoxLayout( m_pPictureTab );
365 //X mainLayout->setMargin( 0 );
366 //X piclabel = new QLabel( m_pPictureTab );
367 //X piclabel->setMinimumSize( 400, 350 );
368 //X mainLayout->addWidget( piclabel );
371 QWidget
*m_pModelTab
= new QWidget();
372 item
= addPage( m_pModelTab
, i18n( "Atom Model" ) );
373 item
->setHeader( i18n( "Atom Model" ) );
374 item
->setIcon( KIcon( "orbits" ) );
375 QVBoxLayout
*modelLayout
= new QVBoxLayout( m_pModelTab
);
376 modelLayout
->setMargin( 0 );
377 wOrbits
= new OrbitsWidget( m_pModelTab
);
378 modelLayout
->addWidget( wOrbits
);
381 m_htmlpages
["misc"] = addHTMLTab( i18n( "Miscellaneous" ), i18n( "Miscellaneous" ), "misc" );
382 m_htmlpages
["isotopes"] = addHTMLTab( i18n( "Isotopes" ), i18n( "Isotopes" ), "isotopes" );
383 m_htmlpages
["new"] = addHTMLTab( i18n( "Data Overview" ), i18n( "Data Overview" ), "data" );
385 // spectrum widget tab
386 QWidget
*m_pSpectrumTab
= new QWidget();
387 item
= addPage( m_pSpectrumTab
, i18n( "Spectrum" ) );
388 item
->setHeader( i18n( "Spectrum" ) );
389 item
->setIcon( KIcon( "spectrum" ) );
390 QVBoxLayout
*spectrumLayout
= new QVBoxLayout( m_pSpectrumTab
);
391 spectrumLayout
->setMargin( 0 );
392 m_spectrumStack
= new QStackedWidget( m_pSpectrumTab
);
393 spectrumLayout
->addWidget( m_spectrumStack
);
394 m_spectrumview
= new SpectrumViewImpl( m_spectrumStack
);
395 m_spectrumview
->setObjectName( "spectrumwidget" );
396 m_spectrumStack
->addWidget( m_spectrumview
);
397 m_spectrumLabel
= new QLabel( m_spectrumStack
);
398 m_spectrumStack
->addWidget( m_spectrumLabel
);
401 void DetailedInfoDlg::reloadContent()
403 // reading the most common data
404 const QString element_name
= m_element
->dataAsString( ChemicalDataObject::name
);
405 const QString element_symbol
= m_element
->dataAsString( ChemicalDataObject::symbol
);
408 setCaption( i18nc( "For example Carbon (6)" , "%1 (%2)", element_name
, m_elementNumber
) );
410 // updating overview tab
411 dTab
->setElement( m_elementNumber
);
413 //X // updating picture tab
414 //X QString picpath = m_picsdir + element_symbol + ".jpg";
415 //X if ( QFile::exists( picpath ) )
417 //X QImage img( picpath, "JPEG" );
418 //X img = img.scaled( 400, 400, Qt::KeepAspectRatio );
419 //X piclabel->setPixmap( QPixmap::fromImage( img ) );
422 //X piclabel->setText( i18n( "No picture of %1 found.", element_name ) );
424 // updating atomic model tab
425 wOrbits
->setElementNumber( m_elementNumber
);
427 wOrbits->setWhatsThis(
428 i18n( "Here you can see the atomic hull of %1. %2 has the configuration %3." )
429 .arg( m_element->dataAsString( ChemicalDataObject::name ) )
430 .arg( m_element->dataAsString( ChemicalDataObject::name ) )
431 .arg( "" ));//m_element->parsedOrbits() ) );
434 // updating html tabs
435 fillHTMLTab( m_htmlpages
["new"], getHtml( DATA
) );
436 fillHTMLTab( m_htmlpages
["misc"], getHtml( MISC
) );
437 fillHTMLTab( m_htmlpages
["isotopes"], getHtml( ISOTOPES
) );
439 Spectrum
* spec
= KalziumDataObject::instance()->spectrum( m_elementNumber
);
441 // updating spectrum widget
444 m_spectrumview
->setSpectrum( spec
);
448 m_spectrumLabel
->setText( i18n( "No spectrum of %1 found.", element_name
) );
449 m_spectrumStack
->setCurrentWidget( m_spectrumLabel
);
453 void DetailedInfoDlg::slotHelp()
455 //TODO fix this stuff...
457 QString chapter
= "infodialog_overview";
458 switch ( activePageIndex() )
461 chapter
= "infodialog_overview";
464 chapter
= "infodialog_orbits";
467 chapter
= "infodialog_chemical";
470 chapter
= "infodialog_energies";
473 chapter
= "infodialog_misc";
476 chapter
= "infodialog_spectrum";
479 chapter
= "infodialog_warnings";
483 KToolInvocation::invokeHelp( "infodialog_spectrum", QLatin1String( "kalzium" ) );
486 void DetailedInfoDlg::slotUser1()
488 setElement( m_ktt
->nextOf( m_elementNumber
) );
491 QString
DetailedInfoDlg::beautifyOrbitalString(const QString
& orbits
)
493 QString newOrbit
= orbits
;
495 QRegExp
reg( "(.*)(f|s|d|p)(\\d+)(.?)" );
497 bool superindexesLeft
= newOrbit
.contains( reg
);
498 while (superindexesLeft
) {
499 newOrbit
= newOrbit
.replace( reg
, "\\1\\2<sup>\\3</sup>\\4" );
501 superindexesLeft
= newOrbit
.contains( reg
);
507 void DetailedInfoDlg::slotUser2()
509 setElement( m_ktt
->previousOf( m_elementNumber
) );
512 #include "detailinfodlg.moc"