mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 02:50:46 -06:00
Merge pull request #7 from MKleusberg/improved-copy-paste
Improve the copy to clipboard feature quite a bit
This commit is contained in:
55
src/ExtendedTableWidget.cpp
Normal file
55
src/ExtendedTableWidget.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QKeySequence>
|
||||
#include <QKeyEvent>
|
||||
#include "ExtendedTableWidget.h"
|
||||
|
||||
ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) :
|
||||
QTableView(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ExtendedTableWidget::copy()
|
||||
{
|
||||
// Get list of selected items
|
||||
QItemSelectionModel* selection = selectionModel();
|
||||
QModelIndexList indices = selection->selectedIndexes();
|
||||
|
||||
// Abort if there's nothing to copy
|
||||
if(indices.size() == 0)
|
||||
return;
|
||||
|
||||
// Sort the items by row, then by column
|
||||
qSort(indices);
|
||||
|
||||
// Go through all the items...
|
||||
QString result;
|
||||
QModelIndex prev = indices.front();
|
||||
indices.removeFirst();
|
||||
foreach(QModelIndex index, indices)
|
||||
{
|
||||
// Add the content of this cell to the clipboard string
|
||||
result.append(QString("\"%1\"").arg(prev.data().toString()));
|
||||
|
||||
// If this is a new row add a line break, if not add a tab for cell separation
|
||||
if(index.row() != prev.row())
|
||||
result.append("\r\n");
|
||||
else
|
||||
result.append("\t");
|
||||
|
||||
prev = index;
|
||||
}
|
||||
result.append(QString("\"%1\"\r\n").arg(indices.last().data().toString())); // And the last cell
|
||||
|
||||
// And finally add it to the clipboard
|
||||
qApp->clipboard()->setText(result);
|
||||
}
|
||||
|
||||
void ExtendedTableWidget::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
// Call a custom copy method when Ctrl-C is pressed
|
||||
if(event->matches(QKeySequence::Copy))
|
||||
copy();
|
||||
else
|
||||
QTableView::keyPressEvent(event);
|
||||
}
|
||||
20
src/ExtendedTableWidget.h
Normal file
20
src/ExtendedTableWidget.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __EXTENDEDTABLEWIDGET_H__
|
||||
#define __EXTENDEDTABLEWIDGET_H__
|
||||
|
||||
#include <QTableView>
|
||||
|
||||
class ExtendedTableWidget : public QTableView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExtendedTableWidget(QWidget* parent = 0);
|
||||
|
||||
private:
|
||||
void copy();
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent* event);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -27,6 +27,7 @@
|
||||
MainWindow::MainWindow(QWidget* parent)
|
||||
: QMainWindow(parent),
|
||||
ui(new Ui::MainWindow),
|
||||
browseTableModel(new QStandardItemModel(this)),
|
||||
editWin(new EditDialog(this)),
|
||||
findWin(0)
|
||||
{
|
||||
@@ -63,7 +64,9 @@ void MainWindow::init()
|
||||
// Create the SQL sytax highlighter
|
||||
sqliteHighlighterTabSql = new SQLiteSyntaxHighlighter(ui->sqlTextEdit->document());
|
||||
|
||||
// Set up DB model
|
||||
// Set up DB models
|
||||
ui->dataTable->setModel(browseTableModel);
|
||||
|
||||
queryResultListModel = new QStandardItemModel(this);
|
||||
ui->queryResultTableView->setModel(queryResultListModel);
|
||||
|
||||
@@ -114,7 +117,6 @@ void MainWindow::init()
|
||||
setAcceptDrops(true);
|
||||
setWindowTitle(QApplication::applicationName());
|
||||
|
||||
|
||||
// Fonts for edit fields
|
||||
QFont font("Monospace");
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
@@ -285,9 +287,10 @@ void MainWindow::populateTable( const QString & tablename, bool keepColumnWidths
|
||||
}
|
||||
|
||||
QString orderby = QString::number(curBrowseOrderByIndex) + " " + (curBrowseOrderByMode == ORDERMODE_ASC ? "ASC" : "DESC");
|
||||
if (!db.browseTable(tablename, orderby)){
|
||||
ui->dataTable->setRowCount( 0 );
|
||||
ui->dataTable->setColumnCount( 0 );
|
||||
if(!db.browseTable(tablename, orderby))
|
||||
{
|
||||
browseTableModel->setRowCount(0);
|
||||
browseTableModel->setColumnCount(0);
|
||||
QApplication::restoreOverrideCursor();
|
||||
if(findWin)
|
||||
findWin->resetFields(db.getTableFields(""));
|
||||
@@ -389,9 +392,10 @@ void MainWindow::addRecord()
|
||||
|
||||
void MainWindow::deleteRecord()
|
||||
{
|
||||
if (ui->dataTable->currentRow()!=-1){
|
||||
int lastselected = ui->dataTable->currentRow();
|
||||
db.deleteRecord(ui->dataTable->currentRow());
|
||||
if(ui->dataTable->currentIndex().row() != -1)
|
||||
{
|
||||
int lastselected = ui->dataTable->currentIndex().row();
|
||||
db.deleteRecord(lastselected);
|
||||
populateTable(db.curBrowseTableName);
|
||||
int nextselected = lastselected ;
|
||||
if (nextselected > db.getRecordCount()){
|
||||
@@ -427,9 +431,9 @@ void MainWindow::updateTableView(int lineToSelect, bool keepColumnWidths)
|
||||
{
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
|
||||
ui->dataTable->setRowCount(db.getRecordCount());
|
||||
ui->dataTable->setColumnCount( db.browseFields.count() );
|
||||
ui->dataTable->setHorizontalHeaderLabels(db.browseFields);
|
||||
browseTableModel->setRowCount(db.getRecordCount());
|
||||
browseTableModel->setColumnCount(db.browseFields.count());
|
||||
browseTableModel->setHorizontalHeaderLabels(db.browseFields);
|
||||
|
||||
rowList tab = db.browseRecs;
|
||||
int maxRecs = db.getRecordCount();
|
||||
@@ -443,17 +447,17 @@ void MainWindow::updateTableView(int lineToSelect, bool keepColumnWidths)
|
||||
for (int i = 0; i < tab.size(); ++i)
|
||||
{
|
||||
rowLabel.setNum(rowNum+1);
|
||||
ui->dataTable->setVerticalHeaderItem(rowNum, new QTableWidgetItem( rowLabel ));
|
||||
browseTableModel->setVerticalHeaderItem(rowNum, new QStandardItem(rowLabel));
|
||||
colNum = 0;
|
||||
QStringList& rt = tab[i];
|
||||
for (int e = 1; e < rt.size(); ++e)
|
||||
{
|
||||
QString& content = rt[e];
|
||||
|
||||
QTableWidgetItem* item = new QTableWidgetItem(content);
|
||||
QStandardItem* item = new QStandardItem(content);
|
||||
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
item->setToolTip(wrapText(content));
|
||||
ui->dataTable->setItem( rowNum, colNum, item);
|
||||
browseTableModel->setItem( rowNum, colNum, item);
|
||||
colNum++;
|
||||
}
|
||||
rowNum++;
|
||||
@@ -462,7 +466,7 @@ void MainWindow::updateTableView(int lineToSelect, bool keepColumnWidths)
|
||||
}
|
||||
|
||||
if(!keepColumnWidths) {
|
||||
for(int i = 0; i < ui->dataTable->columnCount(); ++i)
|
||||
for(int i=0;i<browseTableModel->columnCount();++i)
|
||||
{
|
||||
ui->dataTable->resizeColumnToContents(i);
|
||||
if( ui->dataTable->columnWidth(i) > 400 )
|
||||
@@ -480,13 +484,13 @@ void MainWindow::selectTableLine(int lineToSelect)
|
||||
{
|
||||
ui->dataTable->clearSelection();
|
||||
ui->dataTable->selectRow(lineToSelect);
|
||||
ui->dataTable->setCurrentCell(lineToSelect, 0);
|
||||
ui->dataTable->scrollToItem(ui->dataTable->itemAt(lineToSelect, 0));
|
||||
ui->dataTable->setCurrentIndex(ui->dataTable->currentIndex().sibling(lineToSelect, 0));
|
||||
ui->dataTable->scrollTo(ui->dataTable->currentIndex().sibling(lineToSelect, 0));
|
||||
}
|
||||
|
||||
void MainWindow::navigatePrevious()
|
||||
{
|
||||
int curRow = ui->dataTable->currentRow();
|
||||
int curRow = ui->dataTable->currentIndex().row();
|
||||
curRow -= 100;
|
||||
if(curRow < 0) curRow = 0;
|
||||
updateTableView(curRow);
|
||||
@@ -495,9 +499,10 @@ void MainWindow::navigatePrevious()
|
||||
|
||||
void MainWindow::navigateNext()
|
||||
{
|
||||
int curRow = ui->dataTable->currentRow();
|
||||
int curRow = ui->dataTable->currentIndex().row();
|
||||
curRow += 100;
|
||||
if(curRow >= ui->dataTable->rowCount()) curRow = ui->dataTable->rowCount()-1;
|
||||
if(curRow >= browseTableModel->rowCount())
|
||||
curRow = browseTableModel->rowCount()-1;
|
||||
updateTableView(curRow);
|
||||
}
|
||||
|
||||
@@ -518,7 +523,7 @@ void MainWindow::setRecordsetLabel()
|
||||
{
|
||||
int from = ui->dataTable->verticalHeader()->visualIndexAt(0) + 1;
|
||||
int to = ui->dataTable->verticalHeader()->visualIndexAt(ui->dataTable->height()) - 1;
|
||||
int total = ui->dataTable->rowCount();
|
||||
int total = browseTableModel->rowCount();
|
||||
if(to == -2)
|
||||
to = total;
|
||||
|
||||
@@ -709,9 +714,9 @@ void MainWindow::updateRecordText(int row, int col, const QString& newtext)
|
||||
QStringList& rt = tab[row];
|
||||
QString& cv = rt[col+1];//must account for rowid
|
||||
|
||||
QTableWidgetItem* item = new QTableWidgetItem(cv);
|
||||
QStandardItem* item = new QStandardItem(cv);
|
||||
item->setToolTip( wrapText(cv) );
|
||||
ui->dataTable->setItem(row, col, item);
|
||||
browseTableModel->setItem(row, col, item);
|
||||
|
||||
}
|
||||
|
||||
@@ -719,7 +724,7 @@ void MainWindow::editWinAway()
|
||||
{
|
||||
editWin->hide();
|
||||
activateWindow();
|
||||
ui->dataTable->setRangeSelected(QTableWidgetSelectionRange(editWin->getCurrentRow(), editWin->getCurrentCol(), editWin->getCurrentRow(), editWin->getCurrentCol()), true);
|
||||
ui->dataTable->setCurrentIndex(ui->dataTable->currentIndex().sibling(editWin->getCurrentRow(), editWin->getCurrentCol()));
|
||||
}
|
||||
|
||||
void MainWindow::editText(int row, int col)
|
||||
@@ -732,9 +737,10 @@ void MainWindow::editText(int row, int col)
|
||||
editWin->show();
|
||||
}
|
||||
|
||||
void MainWindow::doubleClickTable( int row, int col )
|
||||
void MainWindow::doubleClickTable(const QModelIndex& index)
|
||||
{
|
||||
if ((row==-1) || (col==-1)){
|
||||
if(!index.isValid())
|
||||
{
|
||||
qDebug("no cell selected");
|
||||
return;
|
||||
}
|
||||
@@ -743,9 +749,7 @@ void MainWindow::doubleClickTable( int row, int col )
|
||||
if(db.getObjectByName(ui->comboBrowseTable->currentText()).gettype() != "table")
|
||||
return;
|
||||
|
||||
int realRow = row;
|
||||
|
||||
editText(realRow , col);
|
||||
editText(index.row(), index.column());
|
||||
}
|
||||
|
||||
void MainWindow::executeQuery()
|
||||
@@ -1125,6 +1129,10 @@ void MainWindow::activateFields(bool enable)
|
||||
|
||||
void MainWindow::browseTableHeaderClicked(int logicalindex)
|
||||
{
|
||||
// Abort if there is more than one column selected because this tells us that the user pretty sure wants to do a range selection instead of sorting data
|
||||
if(ui->dataTable->selectionModel()->selectedColumns().count() > 1)
|
||||
return;
|
||||
|
||||
// instead of the column name we just use the column index, +2 because 'rowid, *' is the projection
|
||||
curBrowseOrderByIndex = logicalindex + 2;
|
||||
curBrowseOrderByMode = curBrowseOrderByMode == ORDERMODE_ASC ? ORDERMODE_DESC : ORDERMODE_ASC;
|
||||
@@ -1132,7 +1140,7 @@ void MainWindow::browseTableHeaderClicked(int logicalindex)
|
||||
|
||||
// select the first item in the column so the header is bold
|
||||
// we might try to select the last selected item
|
||||
ui->dataTable->setCurrentCell(0, logicalindex);
|
||||
ui->dataTable->setCurrentIndex(ui->dataTable->currentIndex().sibling(0, logicalindex));
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent(QResizeEvent*)
|
||||
|
||||
@@ -14,6 +14,7 @@ class SQLiteSyntaxHighlighter;
|
||||
class QStandardItemModel;
|
||||
class QIntValidator;
|
||||
class QLabel;
|
||||
class QModelIndex;
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
@@ -51,6 +52,7 @@ private:
|
||||
|
||||
Ui::MainWindow* ui;
|
||||
|
||||
QStandardItemModel *browseTableModel;
|
||||
QStandardItemModel *queryResultListModel;
|
||||
QMenu *popupTableMenu;
|
||||
QMenu *popupFieldMenu;
|
||||
@@ -128,7 +130,7 @@ private slots:
|
||||
virtual void updateRecordText( int row, int col, const QString& newtext );
|
||||
virtual void editWinAway();
|
||||
virtual void editText( int row, int col );
|
||||
virtual void doubleClickTable( int row, int col );
|
||||
virtual void doubleClickTable(const QModelIndex& index);
|
||||
virtual void executeQuery();
|
||||
virtual void importTableFromCSV();
|
||||
virtual void exportTableToCSV();
|
||||
|
||||
@@ -205,12 +205,12 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="dataTable">
|
||||
<widget class="ExtendedTableWidget" name="dataTable">
|
||||
<property name="whatsThis">
|
||||
<string>This is the database view. You can double-click any record to edit its contents in the cell editor window.</string>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
@@ -317,7 +317,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>763</width>
|
||||
<height>494</height>
|
||||
<height>444</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
@@ -843,7 +843,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="queryResultTableView">
|
||||
<widget class="ExtendedTableWidget" name="queryResultTableView">
|
||||
<property name="toolTip">
|
||||
<string>Query generated data</string>
|
||||
</property>
|
||||
@@ -854,7 +854,7 @@
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
@@ -1399,6 +1399,11 @@
|
||||
<extends>QTextEdit</extends>
|
||||
<header>sqltextedit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ExtendedTableWidget</class>
|
||||
<extends>QTableView</extends>
|
||||
<header>ExtendedTableWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>dbTreeWidget</tabstop>
|
||||
@@ -1697,22 +1702,6 @@
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>dataTable</sender>
|
||||
<signal>cellDoubleClicked(int,int)</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>doubleClickTable(int,int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>99</x>
|
||||
<y>113</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>299</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>mainTab</sender>
|
||||
<signal>currentChanged(int)</signal>
|
||||
@@ -2129,6 +2118,22 @@
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>dataTable</sender>
|
||||
<signal>doubleClicked(QModelIndex)</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>doubleClickTable(QModelIndex)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>399</x>
|
||||
<y>211</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>299</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>fileOpen()</slot>
|
||||
@@ -2143,7 +2148,7 @@
|
||||
<slot>browseRefresh()</slot>
|
||||
<slot>compact()</slot>
|
||||
<slot>helpWhatsThis()</slot>
|
||||
<slot>doubleClickTable(int,int)</slot>
|
||||
<slot>doubleClickTable(QModelIndex)</slot>
|
||||
<slot>browseTableHeaderClicked(int)</slot>
|
||||
<slot>mainTabSelected(int)</slot>
|
||||
<slot>executeQuery()</slot>
|
||||
@@ -2169,5 +2174,6 @@
|
||||
<slot>deleteField()</slot>
|
||||
<slot>loadPragmas()</slot>
|
||||
<slot>savePragmas()</slot>
|
||||
<slot>copy()</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
|
||||
@@ -24,7 +24,8 @@ HEADERS += \
|
||||
ExportCsvDialog.h \
|
||||
ImportCsvDialog.h \
|
||||
sqltextedit.h \
|
||||
sqlitetypes.h
|
||||
sqlitetypes.h \
|
||||
ExtendedTableWidget.h
|
||||
|
||||
SOURCES += \
|
||||
sqlitedb.cpp \
|
||||
@@ -41,7 +42,8 @@ SOURCES += \
|
||||
ExportCsvDialog.cpp \
|
||||
ImportCsvDialog.cpp \
|
||||
sqltextedit.cpp \
|
||||
sqlitetypes.cpp
|
||||
sqlitetypes.cpp \
|
||||
ExtendedTableWidget.cpp
|
||||
|
||||
# create a unittest option
|
||||
CONFIG(unittest) {
|
||||
|
||||
Reference in New Issue
Block a user