Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F102293
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
34 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/dialogs/uploaddialog.cpp b/dialogs/uploaddialog.cpp
new file mode 100644
index 0000000..034e76d
--- /dev/null
+++ b/dialogs/uploaddialog.cpp
@@ -0,0 +1,219 @@
+#include "uploaddialog.h"
+#include "ui_uploaddialog.h"
+
+#include "../tools/os.h"
+#include "../tools/qxtcsvmodel.h"
+#include "../tools/uploader.h"
+#include "../tools/screenshotmanager.h"
+
+#include <QMessageBox>
+#include <QFile>
+#include <QDesktopServices>
+#include <QFileSystemWatcher>
+#include <QUrl>
+#include <QMenu>
+#include <QFileInfo>
+#include <QClipboard>
+#include <QDir>
+#include <QSortFilterProxyModel>
+#include <QDebug>
+
+UploadDialog::UploadDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::UploadDialog)
+{
+ ui->setupUi(this);
+
+ if (os::aeroGlass(this)) {
+ layout()->setMargin(2);
+ }
+
+ ui->filterEdit->setText(tr("Filter.."));
+ ui->filterEdit->installEventFilter(this);
+
+ QFile historyFile(ScreenshotManager::instance()->historyPath());
+
+ if (!historyFile.exists())
+ {
+ ui->tableView->setEnabled(false);
+ return;
+ }
+
+ QFileSystemWatcher *watcher = new QFileSystemWatcher(QStringList() << historyFile.fileName(), this);
+ connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(reloadHistory()));
+
+ reloadHistory();
+
+ ui->tableView->setTextElideMode(Qt::ElideLeft);
+ ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ ui->tableView->setAlternatingRowColors(true);
+ ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
+ ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
+ ui->tableView->setSortingEnabled(true);
+
+ if (ui->tableView->model()->rowCount() > 0)
+ {
+ ui->clearButton->setEnabled(true);
+ ui->filterEdit->setEnabled(true);
+ }
+
+ connect(ui->uploadButton, SIGNAL(clicked()), this, SLOT(upload()));
+ connect(ui->clearButton , SIGNAL(clicked()), this, SLOT(clear()));
+ connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged(QItemSelection,QItemSelection)));
+ connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(open(QModelIndex)));
+ connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenu(QPoint)));
+
+}
+
+UploadDialog::~UploadDialog()
+{
+ delete ui;
+}
+
+void UploadDialog::contextMenu(QPoint point)
+{
+ mContextIndex = ui->tableView->indexAt(point);;
+
+ QMenu contextMenu(ui->tableView);
+
+ QAction copyAction((mContextIndex.column() == 0) ? tr("Copy Path") : tr("Copy URL"), &contextMenu);
+ connect(©Action, SIGNAL(triggered()), this, SLOT(copy()));
+ contextMenu.addAction(©Action);
+
+ QAction locationAction(tr("Open Location"), &contextMenu);
+
+ if (mContextIndex.column() == 0)
+ {
+ connect(&locationAction, SIGNAL(triggered()), this, SLOT(location()));
+ contextMenu.addAction(&locationAction);
+ }
+ else if (mContextIndex.data().toString() == QObject::tr("- not uploaded -")) {
+ copyAction.setEnabled(false);
+ }
+
+ contextMenu.exec(QCursor::pos());
+}
+
+void UploadDialog::copy()
+{
+ qApp->clipboard()->setText(mContextIndex.data().toString());
+}
+
+void UploadDialog::location()
+{
+ QDesktopServices::openUrl("file:///" + QFileInfo(mContextIndex.data().toString()).absolutePath());
+}
+
+void UploadDialog::selectionChanged(QItemSelection selected, QItemSelection deselected)
+{
+ Q_UNUSED(deselected);
+
+ QModelIndex index = selected.indexes().at(0);
+
+ QString screenshot, url;
+
+ if (index.column() == 0) {
+ screenshot = index.data().toString();
+ url = ui->tableView->model()->index(index.row(), 1).data().toString();
+ }
+ else {
+ screenshot = ui->tableView->model()->index(index.row(), 0).data().toString();
+ url = index.data().toString();
+ }
+
+ mSelectedScreenshot = screenshot;
+
+ ui->uploadButton->setEnabled((url == QObject::tr("- not uploaded -") && QFile::exists(screenshot)));
+}
+
+void UploadDialog::open(QModelIndex index)
+{
+ if (index.column() == 0) {
+ QDesktopServices::openUrl(QUrl("file:///" + index.data().toString()));
+ }
+ else {
+ QDesktopServices::openUrl(index.data().toUrl());
+ }
+}
+
+void UploadDialog::reloadHistory()
+{
+ if (ui->tableView->model()) {
+ ui->tableView->model()->deleteLater();
+ }
+
+ QFile historyFile(ScreenshotManager::instance()->historyPath());
+
+ QxtCsvModel *model = new QxtCsvModel(&historyFile, this, false, '|');
+ model->setHeaderData(QStringList() << tr("Screenshot") << tr("URL"));
+
+ mFilterModel = new QSortFilterProxyModel(model);
+ mFilterModel->setSourceModel(model);
+ mFilterModel->setDynamicSortFilter(true);
+
+ ui->tableView->setModel(mFilterModel);
+
+ ui->tableView->horizontalHeader()->setClickable(false);
+ ui->tableView->horizontalHeader()->setMovable(false);
+
+ ui->tableView->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
+ ui->tableView->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents);
+
+ ui->tableView->verticalHeader()->hide();
+
+ ui->tableView->scrollToBottom();
+}
+
+void UploadDialog::upload()
+{
+ Uploader::instance()->upload(mSelectedScreenshot);
+ ui->uploadButton->setEnabled(false);
+}
+
+void UploadDialog::clear()
+{
+ if (QMessageBox::question(this,
+ tr("Clearing the screenshot history"),
+ tr("Are you sure you want to clear your entire screenshot history?\nThis cannot be undone."),
+ tr("Clear History"),
+ tr("Don't Clear")) == 1) {
+ return;
+ }
+
+ QFile::remove(ScreenshotManager::instance()->historyPath());
+
+ ui->tableView->model()->deleteLater();
+ ui->tableView->setEnabled(false);
+ ui->clearButton->setEnabled(false);
+}
+
+bool UploadDialog::eventFilter(QObject *object, QEvent *event)
+{
+ if (object == ui->filterEdit) {
+ if (event->type() == QEvent::FocusIn)
+ {
+ if (ui->filterEdit->text() == tr("Filter..")) {
+ ui->filterEdit->setStyleSheet("");
+ ui->filterEdit->setText("");
+ mFilterModel->setFilterWildcard("");
+ }
+ }
+ else if (event->type() == QEvent::FocusOut)
+ {
+ if (ui->filterEdit->text() == "") {
+ ui->filterEdit->setStyleSheet("color: palette(mid);");
+ ui->filterEdit->setText(tr("Filter.."));
+ }
+ }
+ else if (event->type() == QEvent::KeyRelease)
+ {
+ if (ui->filterEdit->text() != tr("Filter..") && !ui->filterEdit->text().isEmpty()) {
+ mFilterModel->setFilterWildcard(ui->filterEdit->text());
+ }
+ else {
+ mFilterModel->setFilterWildcard("");
+ }
+ }
+ }
+ return QDialog::eventFilter(object, event);
+}
diff --git a/dialogs/uploaddialog.h b/dialogs/uploaddialog.h
new file mode 100644
index 0000000..2e372ee
--- /dev/null
+++ b/dialogs/uploaddialog.h
@@ -0,0 +1,41 @@
+#ifndef UPLOADDIALOG_H
+#define UPLOADDIALOG_H
+
+#include <QDialog>
+#include <QItemSelection>
+
+
+namespace Ui {
+ class UploadDialog;
+}
+
+class QSortFilterProxyModel;
+class UploadDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit UploadDialog(QWidget *parent = 0);
+ ~UploadDialog();
+
+private slots:
+ void copy();
+ void location();
+ void contextMenu(QPoint point);
+ void selectionChanged(QItemSelection selected, QItemSelection deselected);
+ void open(QModelIndex index);
+ void reloadHistory();
+ void upload();
+ void clear();
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event);
+
+private:
+ Ui::UploadDialog *ui;
+ QSortFilterProxyModel *mFilterModel;
+ QString mSelectedScreenshot;
+ QModelIndex mContextIndex;
+};
+
+#endif // UPLOADDIALOG_H
diff --git a/dialogs/uploaddialog.ui b/dialogs/uploaddialog.ui
new file mode 100644
index 0000000..5edf09a
--- /dev/null
+++ b/dialogs/uploaddialog.ui
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UploadDialog</class>
+ <widget class="QDialog" name="UploadDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>327</width>
+ <height>252</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Screenshot History</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../lightscreen.qrc">
+ <normaloff>:/icons/view-history</normaloff>:/icons/view-history</iconset>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item>
+ <widget class="QLineEdit" name="filterEdit">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">color: palette(mid);</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTableView" name="tableView"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="clearButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Clear</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="uploadButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Upload</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="closeButton">
+ <property name="text">
+ <string>Close</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../lightscreen.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>closeButton</sender>
+ <signal>clicked()</signal>
+ <receiver>UploadDialog</receiver>
+ <slot>close()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>279</x>
+ <y>230</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>163</x>
+ <y>125</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/qxtcsvmodel.cpp b/tools/qxtcsvmodel.cpp
new file mode 100644
index 0000000..e61f539
--- /dev/null
+++ b/tools/qxtcsvmodel.cpp
@@ -0,0 +1,552 @@
+/****************************************************************************
+** Copyright (c) 2006 - 2011, the LibQxt project.
+** See the Qxt AUTHORS file for a list of authors and copyright holders.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the LibQxt project nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+** <http://libqxt.org> <foundation@libqxt.org>
+*****************************************************************************/
+
+/*!
+\class QxtCsvModel
+\inmodule QxtCore
+\brief The QxtCsvModel class provides a QAbstractTableModel for CSV Files
+ */
+
+
+
+#include "qxtcsvmodel.h"
+#include <QFile>
+#include <QTextStream>
+#include <QDebug>
+
+class QxtCsvModelPrivate : public QxtPrivate<QxtCsvModel>
+{
+public:
+ QxtCsvModelPrivate() : csvData(), header(), maxColumn(0), quoteMode(QxtCsvModel::DefaultQuoteMode)
+ {}
+ friend class QxtCsvModel;
+
+ QList<QStringList> csvData;
+ QStringList header;
+ int maxColumn;
+ QxtCsvModel::QuoteMode quoteMode;
+};
+
+/*!
+ Creates an empty QxtCsvModel with parent \a parent.
+ */
+QxtCsvModel::QxtCsvModel(QObject *parent) : QAbstractTableModel(parent)
+{
+ QXT_INIT_PRIVATE(QxtCsvModel);
+}
+
+/*!
+ Creates a QxtCsvModel with the parent \a parent and content loaded from \a file.
+
+ See \a setSource for information on the \a withHeader and \a separator properties, or
+ if you need control over the quoting method or codec used to parse the file.
+
+ \sa setSource
+ */
+QxtCsvModel::QxtCsvModel(QIODevice *file, QObject *parent, bool withHeader, QChar separator) : QAbstractTableModel(parent)
+{
+ QXT_INIT_PRIVATE(QxtCsvModel);
+ setSource(file, withHeader, separator);
+}
+
+/*!
+ \overload
+
+ Creates a QxtCsvModel with the parent \a parent and content loaded from \a file.
+
+ See \a setSource for information on the \a withHeader and \a separator properties, or
+ if you need control over the quoting method or codec used to parse the file.
+
+ \sa setSource
+ */
+QxtCsvModel::QxtCsvModel(const QString filename, QObject *parent, bool withHeader, QChar separator) : QAbstractTableModel(parent)
+{
+ QXT_INIT_PRIVATE(QxtCsvModel);
+ QFile src(filename);
+ setSource(&src, withHeader, separator);
+}
+
+QxtCsvModel::~QxtCsvModel()
+{}
+
+/*!
+ \reimp
+ */
+int QxtCsvModel::rowCount(const QModelIndex& parent) const
+{
+ if (parent.row() != -1 && parent.column() != -1) return 0;
+ return qxt_d().csvData.count();
+}
+
+/*!
+ \reimp
+ */
+int QxtCsvModel::columnCount(const QModelIndex& parent) const
+{
+ if (parent.row() != -1 && parent.column() != -1) return 0;
+ return qxt_d().maxColumn;
+}
+
+/*!
+ \reimp
+ */
+QVariant QxtCsvModel::data(const QModelIndex& index, int role) const
+{
+ if(index.parent() != QModelIndex()) return QVariant();
+ if(role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::ToolTipRole || role == Qt::UserRole) {
+ if(index.row() < 0 || index.column() < 0 || index.row() >= rowCount())
+ return QVariant();
+ const QStringList& row = qxt_d().csvData[index.row()];
+ if(index.column() >= row.length())
+ return QVariant();
+ return row[index.column()];
+ }
+ return QVariant();
+}
+
+/*!
+ \reimp
+ */
+QVariant QxtCsvModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if(section < qxt_d().header.count() && orientation == Qt::Horizontal && (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole))
+ return qxt_d().header[section];
+ else
+ return QAbstractTableModel::headerData(section, orientation, role);
+}
+
+/*!
+ \overload
+
+ Reads in a CSV file from the provided \a file using \a codec.
+ */
+void QxtCsvModel::setSource(const QString filename, bool withHeader, QChar separator, QTextCodec* codec)
+{
+ QFile src(filename);
+ setSource(&src, withHeader, separator, codec);
+}
+
+/*!
+ Reads in a CSV file from the provided \a file using \a codec.
+
+ The value of \a separator will be used to delimit fields, subject to the specified \a quoteMode.
+ If \a withHeader is set to true, the first line of the file will be used to populate the model's
+ horizontal header.
+
+ \sa quoteMode
+ */
+void QxtCsvModel::setSource(QIODevice *file, bool withHeader, QChar separator, QTextCodec* codec)
+{
+ QxtCsvModelPrivate* d_ptr = &qxt_d();
+ bool headerSet = !withHeader;
+ if(!file->isOpen())
+ file->open(QIODevice::ReadOnly);
+ if(withHeader)
+ d_ptr->maxColumn = 0;
+ else
+ d_ptr->maxColumn = d_ptr->header.size();
+ d_ptr->csvData.clear();
+ QStringList row;
+ QString field;
+ QChar quote;
+ QChar ch, buffer(0);
+ bool readCR = false;
+ QTextStream stream(file);
+ if(codec) {
+ stream.setCodec(codec);
+ } else {
+ stream.setAutoDetectUnicode(true);
+ }
+ while(!stream.atEnd()) {
+ if(buffer != QChar(0)) {
+ ch = buffer;
+ buffer = QChar(0);
+ } else {
+ stream >> ch;
+ }
+ if(ch == '\n' && readCR)
+ continue;
+ else if(ch == '\r')
+ readCR = true;
+ else
+ readCR = false;
+ if(ch != separator && (ch.category() == QChar::Separator_Line || ch.category() == QChar::Separator_Paragraph || ch.category() == QChar::Other_Control)) {
+ row << field;
+ field.clear();
+ if(!row.isEmpty()) {
+ if(!headerSet) {
+ d_ptr->header = row;
+ headerSet = true;
+ } else {
+ d_ptr->csvData.append(row);
+ }
+ if(row.length() > d_ptr->maxColumn) {
+ d_ptr->maxColumn = row.length();
+ }
+ }
+ row.clear();
+ } else if((d_ptr->quoteMode & DoubleQuote && ch == '"') || (d_ptr->quoteMode & SingleQuote && ch == '\'')) {
+ quote = ch;
+ do {
+ stream >> ch;
+ if(ch == '\\' && d_ptr->quoteMode & BackslashEscape) {
+ stream >> ch;
+ } else if(ch == quote) {
+ if(d_ptr->quoteMode & TwoQuoteEscape) {
+ stream >> buffer;
+ if(buffer == quote) {
+ buffer = QChar(0);
+ field.append(ch);
+ continue;
+ }
+ }
+ break;
+ }
+ field.append(ch);
+ } while(!stream.atEnd());
+ } else if(ch == separator) {
+ row << field;
+ field.clear();
+ } else {
+ field.append(ch);
+ }
+ }
+ if(!field.isEmpty())
+ row << field;
+ if(!row.isEmpty()) {
+ if(!headerSet)
+ d_ptr->header = row;
+ else
+ d_ptr->csvData.append(row);
+ }
+ file->close();
+}
+
+/*!
+ Sets the horizontal headers of the model to the values provided in \a data.
+ */
+void QxtCsvModel::setHeaderData(const QStringList& data)
+{
+ qxt_d().header = data;
+ emit headerDataChanged(Qt::Horizontal, 0, data.count());
+}
+
+/*!
+ \reimp
+ */
+bool QxtCsvModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant& value, int role)
+{
+ if(orientation != Qt::Horizontal) return false; // We don't support the vertical header
+ if(role != Qt::DisplayRole || role != Qt::EditRole) return false; // We don't support any other roles
+ if(section < 0) return false; // Bogus input
+ while(section > qxt_d().header.size()) {
+ qxt_d().header << QString();
+ }
+ qxt_d().header[section] = value.toString();
+ emit headerDataChanged(Qt::Horizontal, section, section);
+ return true;
+}
+
+/*!
+ \reimp
+ */
+bool QxtCsvModel::setData(const QModelIndex& index, const QVariant& data, int role)
+{
+ if (index.parent() != QModelIndex()) return false;
+
+ if(role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) {
+ if(index.row() >= rowCount() || index.column() >= columnCount() || index.row() < 0 || index.column() < 0) return false;
+ QStringList& row = qxt_d().csvData[index.row()];
+ while(row.length() <= index.column())
+ row << QString();
+ row[index.column()] = data.toString();
+ emit dataChanged(index, index);
+ return true;
+ }
+ return false;
+}
+
+/*!
+ \reimp
+ */
+bool QxtCsvModel::insertRow(int row, const QModelIndex& parent)
+{
+ return insertRows(row, 1, parent);
+}
+
+/*!
+ \reimp
+ */
+bool QxtCsvModel::insertRows(int row, int count, const QModelIndex& parent)
+{
+ if (parent != QModelIndex() || row < 0) return false;
+ emit beginInsertRows(parent, row, row + count);
+ QxtCsvModelPrivate& d_ptr = qxt_d();
+ if(row >= rowCount()) {
+ for(int i = 0; i < count; i++) d_ptr.csvData << QStringList();
+ } else {
+ for(int i = 0; i < count; i++) d_ptr.csvData.insert(row, QStringList());
+ }
+ emit endInsertRows();
+ return true;
+}
+
+/*!
+ \reimp
+ */
+bool QxtCsvModel::removeRow(int row, const QModelIndex& parent)
+{
+ return removeRows(row, 1, parent);
+}
+
+/*!
+ \reimp
+ */
+bool QxtCsvModel::removeRows(int row, int count, const QModelIndex& parent)
+{
+ if (parent != QModelIndex() || row < 0) return false;
+ if (row >= rowCount()) return false;
+ if (row + count >= rowCount()) count = rowCount() - row;
+ emit beginRemoveRows(parent, row, row + count);
+ QxtCsvModelPrivate& d_ptr = qxt_d();
+ for (int i = 0;i < count;i++)
+ d_ptr.csvData.removeAt(row);
+ emit endRemoveRows();
+ return true;
+}
+
+/*!
+ \reimp
+ */
+bool QxtCsvModel::insertColumn(int col, const QModelIndex& parent)
+{
+ return insertColumns(col, 1, parent);
+}
+
+/*!
+ \reimp
+ */
+bool QxtCsvModel::insertColumns(int col, int count, const QModelIndex& parent)
+{
+ if (parent != QModelIndex() || col < 0) return false;
+ emit beginInsertColumns(parent, col, col + count);
+ QxtCsvModelPrivate& d_ptr = qxt_d();
+ for(int i = 0; i < rowCount(); i++) {
+ QStringList& row = d_ptr.csvData[i];
+ while(col >= row.length()) row.append(QString());
+ for(int j = 0; j < count; j++) {
+ row.insert(col, QString());
+ }
+ }
+ for(int i = 0; i < count ;i++)
+ d_ptr.header.insert(col, QString());
+ d_ptr.maxColumn += count;
+ emit endInsertColumns();
+ return true;
+}
+
+/*!
+ \reimp
+ */
+bool QxtCsvModel::removeColumn(int col, const QModelIndex& parent)
+{
+ return removeColumns(col, 1, parent);
+}
+
+/*!
+ \reimp
+ */
+bool QxtCsvModel::removeColumns(int col, int count, const QModelIndex& parent)
+{
+ if (parent != QModelIndex() || col < 0) return false;
+ if (col >= columnCount()) return false;
+ if (col + count >= columnCount()) count = columnCount() - col;
+ emit beginRemoveColumns(parent, col, col + count);
+ QxtCsvModelPrivate& d_ptr = qxt_d();
+ QString before, after;
+ for(int i = 0; i < rowCount(); i++) {
+ for(int j = 0; j < count; j++) {
+ d_ptr.csvData[i].removeAt(col);
+ }
+ }
+ for(int i = 0; i < count; i++)
+ d_ptr.header.removeAt(col);
+ emit endRemoveColumns();
+ return true;
+}
+
+static QString qxt_addCsvQuotes(QxtCsvModel::QuoteMode mode, QString field)
+{
+ bool addDoubleQuotes = ((mode & QxtCsvModel::DoubleQuote) && field.contains('"'));
+ bool addSingleQuotes = ((mode & QxtCsvModel::SingleQuote) && field.contains('\''));
+ bool quoteField = (mode & QxtCsvModel::AlwaysQuoteOutput) || addDoubleQuotes || addSingleQuotes;
+ if(quoteField && !addDoubleQuotes && !addSingleQuotes) {
+ if(mode & QxtCsvModel::DoubleQuote)
+ addDoubleQuotes = true;
+ else if(mode & QxtCsvModel::SingleQuote)
+ addSingleQuotes = true;
+ }
+ if(mode & QxtCsvModel::BackslashEscape) {
+ if(addDoubleQuotes)
+ return '"' + field.replace("\\", "\\\\").replace("\"", "\\\"") + '"';
+ if(addSingleQuotes)
+ return '\'' + field.replace("\\", "\\\\").replace("'", "\\'") + '\'';
+ } else {
+ if(addDoubleQuotes)
+ return '"' + field.replace("\"", "\"\"") + '"';
+ if(addSingleQuotes)
+ return '\'' + field.replace("'", "''") + '\'';
+ }
+ return field;
+}
+
+/*!
+ Outputs the content of the model as a CSV file to the device \a dest using \a codec.
+
+ Fields in the output file will be separated by \a separator. Set \a withHeader to true
+ to output a row of headers at the top of the file.
+ */
+void QxtCsvModel::toCSV(QIODevice* dest, bool withHeader, QChar separator, QTextCodec* codec)
+{
+ QxtCsvModelPrivate& d_ptr = qxt_d();
+ int row, col, rows, cols;
+ rows = rowCount();
+ cols = columnCount();
+ QString data;
+ if(!dest->isOpen()) dest->open(QIODevice::WriteOnly | QIODevice::Truncate);
+ QTextStream stream(dest);
+ if(codec) stream.setCodec(codec);
+ if(withHeader) {
+ data = "";
+ for(col = 0; col < cols; ++col) {
+ if(col > 0) data += separator;
+ data += qxt_addCsvQuotes(d_ptr.quoteMode, d_ptr.header.at(col));
+ }
+ stream << data << endl;
+ }
+ for(row = 0; row < rows; ++row)
+ {
+ const QStringList& rowData = d_ptr.csvData[row];
+ data = "";
+ for(col = 0; col < cols; ++col) {
+ if(col > 0) data += separator;
+ if(col < rowData.length())
+ data += qxt_addCsvQuotes(d_ptr.quoteMode, rowData.at(col));
+ else
+ data += qxt_addCsvQuotes(d_ptr.quoteMode, QString());;
+ }
+ stream << data << endl;
+ }
+ stream << flush;
+ dest->close();
+}
+
+/*!
+ \overload
+
+ Outputs the content of the model as a CSV file to the file specified by \a filename using \a codec.
+
+ Fields in the output file will be separated by \a separator. Set \a withHeader to true
+ to output a row of headers at the top of the file.
+ */
+void QxtCsvModel::toCSV(const QString filename, bool withHeader, QChar separator, QTextCodec* codec)
+{
+ QFile dest(filename);
+ toCSV(&dest, withHeader, separator, codec);
+}
+
+/*!
+ \reimp
+ */
+Qt::ItemFlags QxtCsvModel::flags(const QModelIndex& index) const
+{
+ return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
+}
+
+/*!
+ * Returns the current quoting mode.
+ * \sa setQuoteMode
+ */
+QxtCsvModel::QuoteMode QxtCsvModel::quoteMode() const
+{
+ return qxt_d().quoteMode;
+}
+
+/*!
+ * Sets the current quoting mode. The default quoting mode is BothQuotes | BackslashEscape.
+ *
+ * The quoting mode determines what kinds of quoting is used for reading and writing CSV files.
+ * \sa quoteMode
+ * \sa QuoteOption
+ */
+void QxtCsvModel::setQuoteMode(QuoteMode mode)
+{
+ qxt_d().quoteMode = mode;
+}
+
+/*!
+ Sets the content of the cell at row \a row and column \a column to \a value.
+
+ \sa text
+ */
+void QxtCsvModel::setText(int row, int column, const QString& value)
+{
+ setData(index(row, column), value);
+}
+
+/*!
+ Fetches the content of the cell at row \a row and column \a column.
+
+ \sa setText
+ */
+QString QxtCsvModel::text(int row, int column) const
+{
+ return data(index(row, column)).toString();
+}
+
+/*!
+ Sets the content of the header for column \a column to \a value.
+
+ \sa headerText
+ */
+void QxtCsvModel::setHeaderText(int column, const QString& value)
+{
+ setHeaderData(column, Qt::Horizontal, value);
+}
+
+/*!
+ Fetches the content of the cell at row \a row and column \a column.
+
+ \sa setText
+ */
+QString QxtCsvModel::headerText(int column) const
+{
+ return headerData(column, Qt::Horizontal).toString();
+}
diff --git a/tools/qxtcsvmodel.h b/tools/qxtcsvmodel.h
new file mode 100644
index 0000000..d3ad26f
--- /dev/null
+++ b/tools/qxtcsvmodel.h
@@ -0,0 +1,172 @@
+#ifndef QXTCSVMODEL_H
+/****************************************************************************
+** Copyright (c) 2006 - 2011, the LibQxt project.
+** See the Qxt AUTHORS file for a list of authors and copyright holders.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the LibQxt project nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+** <http://libqxt.org> <foundation@libqxt.org>
+*****************************************************************************/
+
+#define QXTCSVMODEL_H
+
+#include <QAbstractTableModel>
+#include <QVariant>
+#include <QIODevice>
+#include <QChar>
+#include <QString>
+#include <QStringList>
+#include <QModelIndex>
+class QTextCodec;
+
+// From qxtglobal.h
+/****************************************************************************
+** This file is derived from code bearing the following notice:
+** The sole author of this file, Adam Higerd, has explicitly disclaimed all
+** copyright interest and protection for the content within. This file has
+** been placed in the public domain according to United States copyright
+** statute and case law. In jurisdictions where this public domain dedication
+** is not legally recognized, anyone who receives a copy of this file is
+** permitted to use, modify, duplicate, and redistribute this file, in whole
+** or in part, with no restrictions or conditions. In these jurisdictions,
+** this file shall be copyright (C) 2006-2008 by Adam Higerd.
+****************************************************************************/
+
+#define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface<PUB, PUB##Private> qxt_d;
+#define QXT_DECLARE_PUBLIC(PUB) friend class PUB;
+#define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this);
+#define QXT_D(PUB) PUB##Private& d = qxt_d()
+#define QXT_P(PUB) PUB& p = qxt_p()
+
+template <typename PUB>
+class QxtPrivate
+{
+public:
+ virtual ~QxtPrivate()
+ {}
+ inline void QXT_setPublic(PUB* pub)
+ {
+ qxt_p_ptr = pub;
+ }
+
+protected:
+ inline PUB& qxt_p()
+ {
+ return *qxt_p_ptr;
+ }
+ inline const PUB& qxt_p() const
+ {
+ return *qxt_p_ptr;
+ }
+
+private:
+ PUB* qxt_p_ptr;
+};
+
+template <typename PUB, typename PVT>
+class QxtPrivateInterface
+{
+ friend class QxtPrivate<PUB>;
+public:
+ QxtPrivateInterface()
+ {
+ pvt = new PVT;
+ }
+ ~QxtPrivateInterface()
+ {
+ delete pvt;
+ }
+
+ inline void setPublic(PUB* pub)
+ {
+ pvt->QXT_setPublic(pub);
+ }
+ inline PVT& operator()()
+ {
+ return *static_cast<PVT*>(pvt);
+ }
+ inline const PVT& operator()() const
+ {
+ return *static_cast<PVT*>(pvt);
+ }
+private:
+ QxtPrivateInterface(const QxtPrivateInterface&) { }
+ QxtPrivateInterface& operator=(const QxtPrivateInterface&) { }
+ QxtPrivate<PUB>* pvt;
+};
+//
+
+class QxtCsvModelPrivate;
+class QxtCsvModel : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ QxtCsvModel(QObject *parent = 0);
+ explicit QxtCsvModel(QIODevice *file, QObject *parent = 0, bool withHeader = false, QChar separator = ',');
+ explicit QxtCsvModel(const QString filename, QObject *parent = 0, bool withHeader = false, QChar separator = ',');
+ ~QxtCsvModel();
+
+ int rowCount(const QModelIndex& parent = QModelIndex()) const;
+ int columnCount(const QModelIndex& parent = QModelIndex()) const;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
+ bool setData(const QModelIndex& index, const QVariant& data, int role = Qt::EditRole);
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ bool setHeaderData(int section, Qt::Orientation orientation, const QVariant& value, int role = Qt::DisplayRole);
+ void setHeaderData(const QStringList& data);
+ QString text(int row, int column) const;
+ void setText(int row, int column, const QString& value);
+ QString headerText(int column) const;
+ void setHeaderText(int column, const QString& value);
+
+
+ bool insertRow(int row, const QModelIndex& parent = QModelIndex());
+ bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex());
+ bool removeRow(int row, const QModelIndex& parent = QModelIndex());
+ bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex());
+ bool insertColumn(int col, const QModelIndex& parent = QModelIndex());
+ bool insertColumns(int col, int count, const QModelIndex& parent = QModelIndex());
+ bool removeColumn(int col, const QModelIndex& parent = QModelIndex());
+ bool removeColumns(int col, int count, const QModelIndex& parent = QModelIndex());
+
+ void setSource(QIODevice *file, bool withHeader = false, QChar separator = ',', QTextCodec* codec = 0);
+ void setSource(const QString filename, bool withHeader = false, QChar separator = ',', QTextCodec* codec = 0);
+
+ void toCSV(QIODevice *file, bool withHeader = false, QChar separator = ',', QTextCodec* codec = 0);
+ void toCSV(const QString filename, bool withHeader = false, QChar separator = ',', QTextCodec* codec = 0);
+
+ enum QuoteOption { NoQuotes = 0, SingleQuote = 1, DoubleQuote = 2, BothQuotes = 3,
+ NoEscape = 0, TwoQuoteEscape = 4, BackslashEscape = 8,
+ AlwaysQuoteOutput = 16, DefaultQuoteMode = BothQuotes | BackslashEscape | AlwaysQuoteOutput };
+ Q_DECLARE_FLAGS(QuoteMode, QuoteOption)
+ QuoteMode quoteMode() const;
+ void setQuoteMode(QuoteMode mode);
+
+ Qt::ItemFlags flags(const QModelIndex& index) const;
+
+private:
+ QXT_DECLARE_PRIVATE(QxtCsvModel)
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QxtCsvModel::QuoteMode)
+
+#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Jan 30, 2:49 PM (5 d, 11 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55393
Default Alt Text
(34 KB)
Attached To
Mode
R63 darkscreen
Attached
Detach File
Event Timeline
Log In to Comment