/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "newpicsdialog.h" #include "smtreeitem.h" #include "helper.h" #include "mappingtreewidget.h" #include "mappingtreemodel.h" NewPicsDialog::NewPicsDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f) { //setup database mDb = QSqlDatabase::database("treedb"); mAddFileQ = new QSqlQuery(mDb); mAddFileQ->prepare("INSERT INTO pics (tfilename, cmd5sum, isize, tformat) VALUES(:fn, :md5, :size, :format)"); mAddMappingQ = new QSqlQuery(mDb); mAddMappingQ->prepare("INSERT INTO pics_mappings (ipics_id, imapping_id) VALUES(:picid, :mapid)"); //files widget mFilesWidget = new QWidget; mFilesV = new QTreeView; mFilesProxy = new QSortFilterProxyModel(this); mFilesModel = new NewPicFilesModel(QStringList() << tr("Filename") << tr("Size") << tr("Val.") << tr("Md5") << tr("Mime type") << tr("Full path"), this); mFilesProxy->setSourceModel(mFilesModel); mFilesV->setModel(mFilesProxy); mFilesV->setSortingEnabled(true); mFilesV->setAlternatingRowColors(true); mFilesV->setColumnHidden(2, true); mAddFiles = new QPushButton(tr("Select...")); connect(mAddFiles, SIGNAL(clicked()), this, SLOT(addFiles())); mRemoveFiles = new QPushButton(tr("Remove")); connect(mRemoveFiles, SIGNAL(clicked()), this, SLOT(removeFiles())); QHBoxLayout *fileButtonLayout = new QHBoxLayout; fileButtonLayout->addStretch(); fileButtonLayout->addWidget(mRemoveFiles); fileButtonLayout->addWidget(mAddFiles); QVBoxLayout *filesLayout = new QVBoxLayout; filesLayout->addWidget(mFilesV); filesLayout->addLayout(fileButtonLayout); mFilesWidget->setLayout(filesLayout); //mapping widget mMappingEditWidget = new MappingEditWidget; //dialog buttons mOk = new QPushButton(tr("Ok")); connect(mOk, SIGNAL(clicked()), this, SLOT(accept())); mCancel = new QPushButton(tr("Cancel")); connect(mCancel, SIGNAL(clicked()), this, SLOT(reject())); QHBoxLayout *dlgButtonLayout = new QHBoxLayout; dlgButtonLayout->addStretch(); dlgButtonLayout->addWidget(mCancel); dlgButtonLayout->addWidget(mOk); //put it together setMinimumWidth(600); setMinimumHeight(400); mTab = new QTabWidget; mTab->addTab(mFilesWidget, tr("Files")); mTab->addTab(mMappingEditWidget, tr("Mappings")); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(mTab); mainLayout->addLayout(dlgButtonLayout); setLayout(mainLayout); } void NewPicsDialog::addFiles(){ QSettings s; QString startDir = s.value("paths/lastpicopendir", QDir::homePath()).toString(); QStringList files = QFileDialog::getOpenFileNames(this, tr("Select pictures"), startDir); if(files.isEmpty()){ return; } QFileInfo fi(files.first()); s.setValue("paths/lastpicopendir", fi.absolutePath()); mFilesV->setSortingEnabled(false); foreach(QString f, files){ mFilesModel->addFile(f); } mFilesV->setSortingEnabled(true); for(int i = 0; i < NewPicFilesModel::NumFields; ++i){ mFilesV->resizeColumnToContents(i); } } void NewPicsDialog::removeFiles(){ QModelIndexList selected = mFilesV->selectionModel()->selectedRows(); if(selected.isEmpty()){ return; } QModelIndexList real; foreach(QModelIndex i, selected){ real << mFilesProxy->mapToSource(i); } QList perm; foreach(QModelIndex i, real){ perm << i; } foreach(QPersistentModelIndex pi, perm){ mFilesModel->removeRows(pi.row(), 1, pi.parent()); } } void NewPicsDialog::accept(){ QList files = mFilesModel->validFiles(); if(files.isEmpty()){ return QDialog::accept(); } QList mappingIds = mMappingEditWidget->mappingIds(); mDb.transaction(); foreach(FileData d, files){ mAddFileQ->bindValue(":fn", d.fileName); mAddFileQ->bindValue(":md5", d.md5sum); mAddFileQ->bindValue(":size", d.size); mAddFileQ->bindValue(":format", d.mimeType); if(mAddFileQ->exec()){ QSqlQuery curPicIdQ("SELECT currval('pics_ipicsid__seq')", mDb); QVariant picId; while(curPicIdQ.next()){ picId = curPicIdQ.value(0); } if(!picId.isValid()){ mDb.rollback(); return; } foreach(int mappingId, mappingIds){ mAddMappingQ->bindValue(":picid", picId); mAddMappingQ->bindValue(":mapid", mappingId); if(!mAddMappingQ->exec()){ mDb.rollback(); return; } } } Helper::moveToArchive(d.fullPath, d.md5sum); } mDb.commit(); return QDialog::accept(); } NewPicFilesModel::NewPicFilesModel(const QStringList &header, QObject *parent) : SmTreeModel(header, parent){ mDb = QSqlDatabase::database("treedb"); mMd5Query = new QSqlQuery(mDb); mMd5Query->prepare("SELECT COUNT(*) FROM pics WHERE cmd5sum = :md5"); } NewPicFilesModel::~NewPicFilesModel(){ delete mMd5Query; mDb = QSqlDatabase(); } Qt::ItemFlags NewPicFilesModel::flags(const QModelIndex &index) const{ Q_UNUSED(index); return (Qt::ItemIsSelectable | Qt::ItemIsEnabled); } QVariant NewPicFilesModel::data(const QModelIndex &index, int role) const{ if(!index.isValid()){ return QVariant(); } SmTreeItem *item = itemAt(index); if(role == FileNameRole){ return item->data(FileName); } if(role == ValidRole){ return item->data(Valid); } if(role == Md5SumRole){ return item->data(Md5Sum); } if(role == MimeTypeRole){ return item->data(MimeType); } if(role == FullPathRole){ return item->data(FullPath); } if(role == Qt::DecorationRole && index.column() == 0){ bool valid = item->data(Valid).toBool(); if(valid){ return QIcon(":/gaping_ass.png"); }else{ return QIcon(":/chastity_belt.png"); } } if(role == Qt::FontRole && index.column() == Md5Sum){ return QFont("courier"); } return SmTreeModel::data(index, role); } bool NewPicFilesModel::setData(const QModelIndex &index, const QVariant &value, int role){ if(role == Qt::EditRole || !index.isValid()){ return false; } SmTreeItem *item = itemAt(index); if(role == FileNameRole){ item->setData(FileName, value); } if(role == SizeRole){ item->setData(Size, value); } if(role == ValidRole){ item->setData(Valid, value); } if(role == Md5SumRole){ item->setData(Md5Sum, value); } if(role == MimeTypeRole){ item->setData(MimeType, value); } if(role == FullPathRole){ item->setData(FullPath, value); } return true; } void NewPicFilesModel::setFiles(const QStringList &paths) { SmTreeItem *rootItem = new SmTreeItem(NumFields); foreach(QString file, paths){ QFileInfo fi(file); QList fileData; if(!fi.exists()){ continue; } QString md5 = Helper::md5Sum(fi.absoluteFilePath()); QString mt = Helper::mimeType(fi.absoluteFilePath()).toLower(); bool valid = true; if(!mt.startsWith("image")){ valid = false; } if(haveMd5(md5)){ valid = false; } fileData << fi.fileName() << valid << md5 << mt << fi.absoluteFilePath(); SmTreeItem *newFile = new SmTreeItem(fileData, rootItem); rootItem->appendChild(newFile); } setRoot(rootItem); } void NewPicFilesModel::addFile(const QString &path){ QFileInfo fi(path); if(!fi.exists()){ return; } QString md5 = Helper::md5Sum(fi.absoluteFilePath()); QString mt = Helper::mimeType(fi.absoluteFilePath()); bool valid = true; if(!mt.startsWith("image")){ valid = false; } if(haveMd5(md5)){ valid = false; } insertRows(0, 1, QModelIndex()); QModelIndex inserted = index(0, 1, QModelIndex()); setData(inserted, fi.fileName(), FileNameRole); setData(inserted, fi.size(), SizeRole); setData(inserted, valid, ValidRole); setData(inserted, md5, Md5SumRole); setData(inserted, mt, MimeTypeRole); setData(inserted, fi.absoluteFilePath(), FullPathRole); } void NewPicFilesModel::removeFile(const QModelIndex &idx){ if(!idx.isValid()){ return; } removeRows(idx.row(), 1, idx.parent()); } QList NewPicFilesModel::validFiles() const { SmTreeItem *rootItem = root(); QList retval; for(int i = 0; i < rootItem->childCount(); ++i){ SmTreeItem *child = rootItem->child(i); if(!child->data(Valid).toBool()){ continue; } FileData data; data.fileName = child->data(FileName).toString(); data.size = child->data(Size).toInt(); data.valid = child->data(Valid).toBool(); data.md5sum = child->data(Md5Sum).toString(); data.mimeType = child->data(MimeType).toString(); data.fullPath = child->data(FullPath).toString(); retval << data; } return retval; } bool NewPicFilesModel::haveMd5(const QString &md5) const { mMd5Query->bindValue(":md5", md5); mMd5Query->exec(); int count = 0; while(mMd5Query->next()){ count = mMd5Query->value(0).toInt(); } return ((count > 0) ? true : false); }