1 /* Copyright (c) 2015  Gerald Knizia
2  *
3  * This file is part of the IboView program (see: http://www.iboview.org)
4  *
5  * IboView is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3.
8  *
9  * IboView is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with bfint (LICENSE). If not, see http://www.gnu.org/licenses/
16  *
17  * Please see IboView documentation in README.txt for:
18  * -- A list of included external software and their licenses. The included
19  *    external software's copyright is not touched by this agreement.
20  * -- Notes on re-distribution and contributions to/further development of
21  *    the IboView software
22  */
23 
24 #include <QItemSelectionModel>
25 #include "IvFindOrbitalsForm.h"
26 #include "IvSettings.h"
27 #include "ui_FindOrbitalsForm.h"
28 
29 // represent a selection of orbitals found via "Find Orbitals"
30 // on selected atoms.
FFoundOrbitalModel(FFoundOrbitalList const & L,FDocument * pDocument,QObject * parent_)31 FFoundOrbitalModel::FFoundOrbitalModel(FFoundOrbitalList const &L, FDocument *pDocument, QObject *parent_)
32    : QAbstractTableModel(parent_), m_pDocument(pDocument), m_FoundOrbitals(L)
33 {
34    connect(m_pDocument, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(documentDataChanged(const QModelIndex &, const QModelIndex &)));
35 }
36 
rowCount(const QModelIndex &) const37 int FFoundOrbitalModel::rowCount(const QModelIndex &/*parent*/) const
38 {
39    return (int)m_FoundOrbitals.size();
40 }
41 
columnCount(const QModelIndex &) const42 int FFoundOrbitalModel::columnCount(const QModelIndex &/*parent*/) const
43 {
44    return 3;
45 }
46 
headerData(int section,Qt::Orientation orientation,int role) const47 QVariant FFoundOrbitalModel::headerData(int section, Qt::Orientation orientation, int role) const
48 {
49    char const *pCaptions[] = {"Sel. Chg.", "Desc.", "Centers/Charges"};
50    if ( orientation == Qt::Horizontal ) {
51       if ( role == Qt::DisplayRole ) {
52          if ((size_t)section < (sizeof(pCaptions)/sizeof(pCaptions[0])))
53             return QString(pCaptions[section]);
54       }
55       if ( role == Qt::FontRole ) {
56             QFont CaptionFont;
57             CaptionFont.setBold(true);
58             return CaptionFont;
59       }
60    }
61 
62    return QVariant();
63 }
64 
data(const QModelIndex & index,int role) const65 QVariant FFoundOrbitalModel::data(const QModelIndex &index, int role) const
66 {
67    int
68       iRow = index.row(),
69       iCol = index.column();
70    if (iRow < 0 && (size_t)iRow < m_FoundOrbitals.size())
71       return QVariant();
72    FFoundOrbital const
73       *pFoundOrbital = &m_FoundOrbitals[iRow];
74    FOrbital const
75       *pOrbital = pFoundOrbital->pOrbital;
76 
77    if ( role == Qt::DisplayRole ) {
78       if (iCol == 0) {
79          QString
80             sChgOnSelected(QString("%1").arg(pFoundOrbital->fSelChg,7,'f',3));
81          if (pFoundOrbital->fSelChg > 1.5)
82             sChgOnSelected.append("*");
83          else
84             sChgOnSelected.append(" ");
85          return QVariant(sChgOnSelected);
86       } else if (iCol == 1) {
87          return QVariant(pOrbital->GetDesc());
88       }else if (iCol == 2) {
89          return QVariant(pOrbital->MakeFullDesc(0.02, FOrbital::ORBDESC_ChargesOnly));
90       }
91       return QVariant();
92    }
93 
94 //    if ( role == Qt::FontRole && iCol == 2 ) {
95 //       QFont MonoFont("");
96 //       MonoFont.setStyleHint(QFont::TypeWriter);
97 //       // ^- there is also QFont::Monospace, but that does not seem to work.
98 //       return MonoFont;
99 //    }
100 
101    if ( pOrbital->Active && iCol == 1 ) {
102       uint32_t dwBaseColor = pOrbital->GetBaseColor();
103       if (dwBaseColor != 0) {
104          if ( role == Qt::BackgroundRole ) return QBrush(QColor(dwBaseColor));
105          if ( role == Qt::ForegroundRole ) return QBrush(Qt::black);
106       } else {
107          if ( role == Qt::BackgroundRole ) return QBrush(QColor(64,96,64));
108          if ( role == Qt::ForegroundRole ) return QBrush(Qt::white);
109       }
110    }
111    return QVariant();
112 }
113 
documentDataChanged(const QModelIndex &,const QModelIndex &)114 void FFoundOrbitalModel::documentDataChanged(const QModelIndex &/*topLeft*/, const QModelIndex &/*bottomRight*/)
115 {
116 //    IvEmit("forwarding FFoundOrbitalModel::documentDataChanged.");
117    // well.. we COULD sort out the right range... or just emit "update all"...
118    emit dataChanged(createIndex(0,0), createIndex(3, m_FoundOrbitals.size()));
119 }
120 
121 
122 
123 
124 
125 
FFindOrbitalsForm(FFoundOrbitalModel * pModel_,QString Title_,QWidget * parent)126 FFindOrbitalsForm::FFindOrbitalsForm(FFoundOrbitalModel *pModel_, QString Title_, QWidget *parent)
127    : QDialog(parent),
128      ui(new Ui::FindOrbitalsForm),
129      m_pModel(pModel_)
130 {
131    ui->setupUi(this);
132    ui->orbitalTable->setWordWrap(false);
133    ui->orbitalTable->setSelectionBehavior(QAbstractItemView::SelectRows);
134 #if QT_VERSION >= 0x050000
135    ui->orbitalTable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
136    ui->orbitalTable->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
137 #else
138    // qt5 doc's say there is a compatibiltiy layer for this.. but it doesn't seem to exist
139    // in my windows qt 5.3.2 version.
140    ui->orbitalTable->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
141    ui->orbitalTable->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
142 #endif
143    ui->orbitalTable->setModel(m_pModel);
144    setWindowTitle(Title_);
145    // todo: connect actions etc (toggle data row, sort).
146 
147    connect(ui->orbitalTable, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(toggleRow(const QModelIndex&)));
148    connect(ui->pushButton_ToggleRows, SIGNAL(clicked()), this, SLOT(toggleSelectedRows()));
149 
150    if (!IvRestoreWindowSize("FindOrbitalsWindow/Size", this))
151       IvGuessSubDialogSize(this);
152 }
153 
~FFindOrbitalsForm()154 FFindOrbitalsForm::~FFindOrbitalsForm()
155 {
156    IvSaveWindowSize("FindOrbitalsWindow/Size", this);
157    delete ui;
158 }
159 
toggleRow(const QModelIndex & index)160 void FFindOrbitalsForm::toggleRow(const QModelIndex &index)
161 {
162    int
163       iRow = index.row();
164    if ((size_t)iRow > m_pModel->m_FoundOrbitals.size())
165       return;
166    FFoundOrbital const
167       *pFoundOrbital = &m_pModel->m_FoundOrbitals[(size_t)iRow];
168 //    IvEmit("trigger row %1", pFoundOrbital->iDataRow);
169 
170    m_pModel->m_pDocument->ToggleDataRow(pFoundOrbital->iDataRow);
171 }
172 
toggleSelectedRows()173 void FFindOrbitalsForm::toggleSelectedRows()
174 {
175    QItemSelectionModel
176       *pSelectionModel = ui->orbitalTable->selectionModel();
177    QModelIndexList
178       SelectedRows = pSelectionModel->selectedRows();
179    QModelIndexList::const_iterator
180       itSel;
181    for (itSel = SelectedRows.begin(); itSel != SelectedRows.end(); ++ itSel) {
182       toggleRow(*itSel);
183    }
184 }
185