1 /****************************************************************************
2 * QTableView with some adjustments like storing header layout               *
3 * (C) 2007 Michal Rudolf <mrudolf@kdewebdev.org>                            *
4 *   Copyright (C) 2012 by Jens Nissen jens-chessx@gmx.net                   *
5 ****************************************************************************/
6 
7 #include "settings.h"
8 #include "tableview.h"
9 
10 #include <QAction>
11 #include <QApplication>
12 #include <QClipboard>
13 #include <QHeaderView>
14 #include <QMenu>
15 #include <QScrollBar>
16 #include <QWheelEvent>
17 
18 #if defined(_MSC_VER) && defined(_DEBUG)
19 #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
20 #define new DEBUG_NEW
21 #endif // _MSC_VER
22 
TableView(QWidget * parent)23 TableView::TableView(QWidget *parent)
24     : QTableView(parent),
25     m_alignDecoration(Qt::AlignCenter),
26     m_posDecoration(QStyleOptionViewItem::Left)
27 {
28     setShowGrid(false);
29     setSelectionBehavior(QAbstractItemView::SelectRows);
30     setSelectionMode(QAbstractItemView::SingleSelection);
31     setWordWrap(false);
32     setTextElideMode(Qt::ElideRight);
33     verticalHeader()->setDefaultSectionSize(fontMetrics().lineSpacing());
34     verticalHeader()->hide();
35     horizontalHeader()->setHighlightSections(false);
36     horizontalHeader()->setStretchLastSection(true);
37 #if QT_VERSION < 0x050000
38     horizontalHeader()->setMovable(true);
39 #else
40     horizontalHeader()->setSectionsMovable(true);
41 #endif
42     setTabKeyNavigation(false);
43     setContextMenuPolicy(Qt::CustomContextMenu);
44     horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
45 
46     connect(horizontalHeader(), SIGNAL(customContextMenuRequested(const QPoint&)),
47             this, SLOT(ShowContextMenu(const QPoint&)));
48     connect(&m_dragTimer, SIGNAL(timeout()), this, SLOT(SlotDragTimer()));
49     m_dragTimer.setSingleShot(true);
50 }
51 
~TableView()52 TableView::~TableView()
53 {
54 }
55 
wheelEvent(QWheelEvent * e)56 void TableView::wheelEvent(QWheelEvent* e)
57 {
58     unsigned int button = e->modifiers() & Qt::KeyboardModifierMask;
59     if (button == (Qt::ControlModifier|Qt::AltModifier))
60     {
61         QFont f = font();
62         int n = e->delta()>0 ? 1 : -1;
63         int fontSize = f.pointSize() + n;
64         setFontSize(fontSize);
65     }
66     QTableView::wheelEvent(e);
67 }
68 
viewOptions() const69 QStyleOptionViewItem TableView::viewOptions() const
70 {
71     QStyleOptionViewItem option = QTableView::viewOptions();
72     option.decorationAlignment = m_alignDecoration;
73     option.decorationPosition = m_posDecoration;
74     return option;
75 }
76 
posDecoration() const77 QStyleOptionViewItem::Position TableView::posDecoration() const
78 {
79     return m_posDecoration;
80 }
81 
setPosDecoration(const QStyleOptionViewItem::Position & posDecoration)82 void TableView::setPosDecoration(const QStyleOptionViewItem::Position &posDecoration)
83 {
84     m_posDecoration = posDecoration;
85 }
86 
alignDecoration() const87 Qt::Alignment TableView::alignDecoration() const
88 {
89     return m_alignDecoration;
90 }
91 
setAlignDecoration(const Qt::Alignment & alignDecoration)92 void TableView::setAlignDecoration(const Qt::Alignment &alignDecoration)
93 {
94     m_alignDecoration = alignDecoration;
95 }
96 
saveConfig()97 void TableView::saveConfig()
98 {
99     if (model())
100     {
101         AppSettings->setLayout(this);
102         AppSettings->beginGroup(objectName());
103         int n = model()->columnCount();
104         AppSettings->setValue("ColumnCount", n);
105         QByteArray visualIndex = horizontalHeader()->saveState();
106         AppSettings->setByteArray("VisualIndex", visualIndex);
107         AppSettings->endGroup();
108     }
109 }
110 
setFontSize(int fontSize)111 void TableView::setFontSize(int fontSize)
112 {
113     fontSize = std::max(fontSize, 8);
114     QFont f = font();
115     f.setPointSize(fontSize);
116     setFont(f);
117 
118     QFontMetrics fm(f);
119     int rowHeight = std::max(minRowHeight(), fm.height()+2);
120 
121     QHeaderView *vh = verticalHeader();
122 #if QT_VERSION < 0x050000
123     vh->setResizeMode(QHeaderView::Fixed);
124 #else
125     vh->sectionResizeMode(QHeaderView::Fixed);
126 #endif
127     vh->setDefaultSectionSize(rowHeight);
128 }
129 
slotReconfigure()130 void TableView::slotReconfigure()
131 {
132     bool sortIndicator = horizontalHeader()->isSortIndicatorShown();
133     AppSettings->layout(this);
134     QString objName = objectName();
135 
136     AppSettings->beginGroup(objName);
137 
138     int n = model()->columnCount();
139     int nRestore = AppSettings->getValue("ColumnCount").toInt();
140     if (n==nRestore)
141     {
142         QByteArray visualIndex = AppSettings->byteArray("VisualIndex");
143         horizontalHeader()->restoreState(visualIndex);
144     }
145     else
146     {
147         for(int i = 0; i < n; ++i)
148         {
149             showColumn(i);
150         }
151         AppSettings->setValue("ColumnCount", n);
152         resizeColumnsToContents();
153     }
154     AppSettings->endGroup();
155 
156     int fontSize = AppSettings->getValue("/General/ListFontSize").toInt();
157     setFontSize(fontSize);
158 
159     horizontalHeader()->setSortIndicatorShown(sortIndicator);
160     update();
161 }
162 
ShowContextMenu(const QPoint & pos)163 void TableView::ShowContextMenu(const QPoint& pos)
164 {
165     QMenu headerMenu;
166     QAction* hide = headerMenu.addAction(tr("Hide Column"));
167 
168     QAction* resizeAll = headerMenu.addAction(tr("Resize visible Columns"));
169     QAction* showAll = headerMenu.addAction(tr("Show all Columns"));
170     headerMenu.addSeparator();
171     QAction* copyHTML = headerMenu.addAction(tr("Copy as HTML"));
172     QAction* copyImage = headerMenu.addAction(tr("Copy as Image"));
173 
174     QAction* selectedItem = headerMenu.exec(mapToGlobal(pos));
175     if(selectedItem == hide)
176     {
177         int column = columnAt(pos.x());
178         if(column > 0)
179         {
180             hideColumn(column);
181         }
182     }
183     else if(selectedItem == showAll)
184     {
185         for(int i = 0; i < model()->columnCount(); ++i)
186         {
187             showColumn(i);
188         }
189     }
190     else if (selectedItem == resizeAll)
191     {
192         resizeColumnsToContents();
193     }
194     else if (selectedItem == copyHTML)
195     {
196         QString html = renderToHTML();
197         QApplication::clipboard()->setText(html);
198     }
199     else if (selectedItem == copyImage)
200     {
201         QImage img = renderToImage();
202         QApplication::clipboard()->setImage(img);
203     }
204 }
205 
renderHTMLitem(int row,int column) const206 QString TableView::renderHTMLitem(int row,int column) const
207 {
208     QString result = "<td>";
209     QVariant data = model()->data(model()->index(row, column));
210     QString s = data.toString();
211     result += s;
212     result += "</td>";
213     return result;
214 }
215 
renderHTMLrow(int row) const216 QString TableView::renderHTMLrow(int row) const
217 {
218     QString result = "<tr>\n";
219     int columns = model()->columnCount();
220     for (int i=0; i<columns; ++i)
221     {
222         result += renderHTMLitem(row,i);
223     }
224     result += "</tr>\n";
225     return result;
226 }
227 
renderHeaderToHTML() const228 QString TableView::renderHeaderToHTML() const
229 {
230     QString result = "<tr>\n";
231     int columns = model()->columnCount();
232     for (int i=0; i<columns; ++i)
233     {
234         result += "<th>";
235         result += horizontalHeader()->model()->headerData(i, Qt::Horizontal).toString();
236         result += "</th>";
237     }
238     result += "</tr>\n";
239     return result;
240 }
241 
renderToHTML() const242 QString TableView::renderToHTML() const
243 {
244     QString result = "<table border='1'>\n";
245     result += renderHeaderToHTML();
246     int rows = model()->rowCount();
247     for (int i=0; i<rows; ++i)
248     {
249         result += renderHTMLrow(i);
250     }
251     result += "</table>\n";
252     return result;
253 }
254 
renderToImage() const255 QImage TableView::renderToImage() const
256 {
257     QTableView* pTableView = new QTableView;
258     pTableView->setModel(model());
259 
260     int width = 0;
261     int height = 0;
262     int columns = model()->columnCount();
263     int rows = model()->rowCount();
264 
265     pTableView->resizeColumnsToContents();
266 
267     for( int i = 0; i < columns; ++i ) {
268         width += pTableView->columnWidth(i);
269     }
270 
271     for( int i = 0; i < rows; ++i ) {
272         height += pTableView->rowHeight(i);
273     }
274 
275     height += horizontalHeader()->height();
276 
277     pTableView->setFixedSize(width, height);
278     pTableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
279     pTableView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
280 
281     QPixmap pixmap(width, height);
282     pixmap.fill(Qt::transparent);
283 
284     pTableView->render(&pixmap);
285     QImage image = pixmap.toImage();
286 
287     delete pTableView;
288     return image;
289 }
290 
startDrag(Qt::DropActions supportedActions)291 void TableView::startDrag(Qt::DropActions supportedActions)
292 {
293     Q_UNUSED(supportedActions);
294     m_dragTimer.stop();
295 }
296 
dragEnterEvent(QDragEnterEvent * event)297 void TableView::dragEnterEvent(QDragEnterEvent *event)
298 {
299     Q_UNUSED(event);
300     m_dragTimer.stop();
301 }
302 
dragMoveEvent(QDragMoveEvent * event)303 void TableView::dragMoveEvent(QDragMoveEvent *event)
304 {
305     Q_UNUSED(event);
306 }
307 
dragLeaveEvent(QDragLeaveEvent * event)308 void TableView::dragLeaveEvent(QDragLeaveEvent *event)
309 {
310     Q_UNUSED(event);
311     m_dragTimer.start(250);
312 }
313 
dropEvent(QDropEvent * event)314 void TableView::dropEvent(QDropEvent *event)
315 {
316     Q_UNUSED(event);
317     m_dragTimer.stop();
318 }
319 
SlotDragTimer()320 void TableView::SlotDragTimer()
321 {
322     //qDebug()<< "TableView::SlotDragTimer" << endl;
323     QPoint p = QCursor::pos();
324     QPoint tl = mapToGlobal(pos());
325     QRect r = rect();
326     if (p.x()>tl.x() && p.x()<tl.x()+r.width())
327     {
328         if (p.y()<tl.y()) // Move above the view
329         {
330             verticalScrollBar()->setValue(verticalScrollBar()->value()-10);
331         }
332         else if (p.y()>tl.y()+r.height()) // Move below the view
333         {
334             verticalScrollBar()->setValue(verticalScrollBar()->value()+10);
335         }
336         m_dragTimer.start();
337     }
338     else // Move to the left or right of the view
339     {
340         m_dragTimer.stop();
341     }
342 }
343 
344