diff options
-rw-r--r-- | mappingtreemodel.cpp | 1 | ||||
-rw-r--r-- | mappingtreemodel.h | 1 | ||||
-rw-r--r-- | mappingtreewidget.cpp | 8 | ||||
-rw-r--r-- | mappingtreewidget.h | 4 | ||||
-rw-r--r-- | pictureswidget.cpp | 228 | ||||
-rw-r--r-- | pictureswidget.h | 83 | ||||
-rw-r--r-- | shemov.cpp | 10 | ||||
-rw-r--r-- | shemov.h | 6 | ||||
-rw-r--r-- | shemov.pro | 6 |
9 files changed, 345 insertions, 2 deletions
diff --git a/mappingtreemodel.cpp b/mappingtreemodel.cpp index a79661e..4cd3f29 100644 --- a/mappingtreemodel.cpp +++ b/mappingtreemodel.cpp @@ -231,6 +231,7 @@ void MappingTreeModel::populate(){ getChildrenRecursive(childItem); } setRoot(rootItem); + emit needExpansion(); } } diff --git a/mappingtreemodel.h b/mappingtreemodel.h index e55f609..fa2cfef 100644 --- a/mappingtreemodel.h +++ b/mappingtreemodel.h @@ -47,6 +47,7 @@ class MappingTreeModel : public SmTreeModel { signals: void mappingTypesChanged(); + void needExpansion(); private: struct mappingType { diff --git a/mappingtreewidget.cpp b/mappingtreewidget.cpp index 00f4738..d9ea7da 100644 --- a/mappingtreewidget.cpp +++ b/mappingtreewidget.cpp @@ -40,6 +40,8 @@ MappingTreeWidget::MappingTreeWidget(QWidget *parent) : QWidget(parent){ mTree->setColumnHidden(2, true); mTree->setAlternatingRowColors(true); mTree->expandAll(); + connect(mModel, SIGNAL(needExpansion()), mTree, SLOT(expandAll())); + connect(mTree->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged())); mTypeBox = new QComboBox; mTypeBox->setModel(mTypesModel); connect(mTypeBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(typeChanged(QString))); @@ -208,6 +210,12 @@ void MappingTreeWidget::editChild(){ } } +void MappingTreeWidget::selectionChanged(){ + QModelIndex sel = selected(); + QModelIndex real = mProxy->mapToSource(sel); + emit mappingChanged(real.data(MappingTreeModel::IdRole).toInt()); +} + const QModelIndex MappingTreeWidget::selected() const{ QModelIndexList sel = mTree->selectionModel()->selectedRows(); if(sel.isEmpty()){ diff --git a/mappingtreewidget.h b/mappingtreewidget.h index 8cb1cce..734d943 100644 --- a/mappingtreewidget.h +++ b/mappingtreewidget.h @@ -39,6 +39,10 @@ class MappingTreeWidget : public QWidget { private slots: void typeChanged(QString type); void editChild(); + void selectionChanged(); + + signals: + void mappingChanged(int); private: const QModelIndex selected() const; diff --git a/pictureswidget.cpp b/pictureswidget.cpp new file mode 100644 index 0000000..4bc2aad --- /dev/null +++ b/pictureswidget.cpp @@ -0,0 +1,228 @@ +/* + 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 <QSplitter> +#include <QHBoxLayout> +#include <QSqlQuery> +#include <QSortFilterProxyModel> +#include <QLocale> +#include <QHideEvent> +#include <QHoverEvent> +#include <QEvent> +#include <QHeaderView> +#include <QSettings> +#include <QMessageBox> +#include <QMenu> +#include <QFile> + +#include "pictureswidget.h" +#include "mappingtreewidget.h" +#include "smtreeitem.h" +#include "helper.h" +#include "hoverwindow.h" + +PicturesWidget::PicturesWidget(QWidget *parent) : QWidget(parent) { + //setup gui + QSplitter *splitter = new QSplitter; + mMappingTree = new MappingTreeWidget; + mPictureView = new PictureView; + connect(mMappingTree, SIGNAL(mappingChanged(int)), mPictureView, SLOT(mappingChanged(int))); + splitter->addWidget(mMappingTree); + splitter->addWidget(mPictureView); + splitter->setStretchFactor(0, 1); + splitter->setStretchFactor(1, 3); + + //put it all togehter + QHBoxLayout *mainLayout = new QHBoxLayout; + mainLayout->addWidget(splitter); + setLayout(mainLayout); +} + +PictureView::PictureView(QWidget *parent) : QTreeView(parent) { + //setup model + mModel = new PicFilesModel(QStringList() << tr("Filename") << tr("SizeNum") << tr("Format") << tr("Full Path") << tr("Id") << tr("Added") << tr("Md5Sum") << tr("Size"), this); + mProxy = new QSortFilterProxyModel(this); + mProxy->setSourceModel(mModel); + setModel(mProxy); + + //read settings + QSettings s; + QByteArray pvHeader = s.value("ui/pvheader").toByteArray(); + mCursorOffset = s.value("ui/cursoroffset").toInt(); + if(!pvHeader.isEmpty()){ + header()->restoreState(pvHeader); + } + + //hover window + mHoverWin = new HoverWindow; + + //misc settings + setSortingEnabled(true); + setAttribute(Qt::WA_Hover); + setSelectionMode(QAbstractItemView::ExtendedSelection); + setAlternatingRowColors(true); + setColumnHidden(1, true); + setColumnHidden(4, true); +} + +void PictureView::mappingChanged(int mapping){ + mModel->setMapping(mapping); + mModel->populate(); + for(int i = 0; i < PicFilesModel::NumFields; ++i){ + resizeColumnToContents(i); + } +} + + +void PictureView::deletePics(){ + QModelIndexList sel = selectionModel()->selectedRows(); + if(sel.isEmpty()){ + return; + } + QString msg = QString(tr("Really delete %1 pics from archive?")).arg(sel.count()); + int retval = QMessageBox::question(this, tr("Question"), msg, QMessageBox::Yes | QMessageBox::No); + if(retval == QMessageBox::No){ + return; + } + QList<QPersistentModelIndex> real; + foreach(QModelIndex i, sel){ + real << QPersistentModelIndex(mProxy->mapToSource(i)); + } + mModel->removeFiles(real); +} + +void PictureView::hideEvent(QHideEvent *){ + QByteArray pvHeader = header()->saveState(); + QSettings s; + s.setValue("ui/pvheader", pvHeader); +} + +bool PictureView::event(QEvent *e){ + QHoverEvent *hEvent = static_cast<QHoverEvent*>(e); + if(!hEvent){ + return QTreeView::event(e); + } + QPoint hotSpot(hEvent->pos().x(), hEvent->pos().y() + mCursorOffset); + QModelIndex curIdx = indexAt(hotSpot); + if(e->type() == QEvent::HoverEnter || e->type() == QEvent::HoverMove){ + if(!curIdx.isValid() || curIdx.column() != PicFilesModel::FileName){ + mHoverWin->setVisible(false); + mCurHover = QModelIndex(); + return true; + } + } + if(e->type() == QEvent::HoverEnter){ + mCurHover = curIdx; + QPixmap pm; + pm.load(mCurHover.data(PicFilesModel::FullPathRole).toString()); + mHoverWin->setPixmap(pm); + mHoverWin->setPos(); + mHoverWin->setCaption(mCurHover.data().toString()); + mHoverWin->setVisible(true); + return true; + } + if(e->type() == QEvent::HoverMove){ + if(curIdx != mCurHover){ + mCurHover = curIdx; + QPixmap pm; + pm.load(mCurHover.data(PicFilesModel::FullPathRole).toString()); + mHoverWin->setPixmap(pm); + mHoverWin->setPos(); + mHoverWin->setCaption(mCurHover.data().toString()); + mHoverWin->setVisible(true); + return true; + } + } + return QTreeView::event(e); +} + +void PictureView::contextMenuEvent(QContextMenuEvent *e){ + QMenu ctxMenu; + ctxMenu.addActions(actions()); + ctxMenu.exec(e->globalPos()); +} + +PicFilesModel::PicFilesModel(const QStringList &headers, QObject *parent) : SmTreeModel(headers, parent) { + //setup database + mDb = QSqlDatabase::database("treedb"); + mPopulateQ = new QSqlQuery(mDb); + mPopulateQ->prepare("SELECT pics.tfilename, pics.isize, pics.tformat, pics.dtadded, pics.cmd5sum, pics.ipicsid FROM pics, pics_mappings WHERE pics_mappings.imapping_id = :mapid AND pics_mappings.ipics_id = pics.ipicsid ORDER BY pics.tfilename"); + mDeleteFileQ = new QSqlQuery(mDb); + mDeleteFileQ->prepare("DELETE FROM pics WHERE ipicsid = :id"); +} + +QVariant PicFilesModel::data(const QModelIndex &index, int role) const { + if(role == Qt::FontRole){ + if(index.column() == Md5Sum){ + return QFont("courier"); + } + } + if(role == Qt::ForegroundRole){ + if(index.column() == SizeDisplay){ + int fileSize = index.data(SizeRole).toInt(); + if(fileSize > 1024 * 1024 * 1024){ + return QColor(Qt::red); + }else{ + return QColor(Qt::green); + } + } + } + SmTreeItem *item = itemAt(index); + if(role == FileNameRole){ + return item->data(FileName); + } + if(role == SizeRole){ + return item->data(Size); + } + if(role == MimeTypeRole){ + return item->data(MimeType); + } + if(role == FullPathRole){ + return item->data(FullPath); + } + if(role == IdRole){ + return item->data(Id); + } + if(role == AddedRole){ + return item->data(Added); + } + if(role == Md5SumRole){ + return item->data(Md5Sum); + } + if(role == SizeDisplayRole){ + return item->data(SizeDisplay); + } + return SmTreeModel::data(index, role); +} + +void PicFilesModel::removeFiles(const QList<QPersistentModelIndex> &files){ + foreach(QPersistentModelIndex pi, files){ + mDeleteFileQ->bindValue(":id", pi.data(IdRole)); + if(mDeleteFileQ->exec()){ + QFile::remove(pi.data(FullPathRole).toString()); + removeRows(pi.row(), 1, QModelIndex()); + } + } +} + +void PicFilesModel::populate(){ + SmTreeItem *root = new SmTreeItem(NumFields); + mPopulateQ->bindValue(":mapid", mMappingId); + if(mPopulateQ->exec()){ + while(mPopulateQ->next()){ + QList<QVariant> data; + data << mPopulateQ->value(0) << mPopulateQ->value(1) << mPopulateQ->value(2); // Filename, size and Mime type + data << Helper::createArchivePath(mPopulateQ->value(0).toString(), mPopulateQ->value(4).toString()); // full path; + data << mPopulateQ->value(5) << mPopulateQ->value(3) << mPopulateQ->value(4); //Id, added and md5 + QLocale l; + data << l.toString(mPopulateQ->value(1).toInt()); + SmTreeItem *child = new SmTreeItem(data, root); + root->appendChild(child); + } + setRoot(root); + } +} diff --git a/pictureswidget.h b/pictureswidget.h new file mode 100644 index 0000000..b0bd277 --- /dev/null +++ b/pictureswidget.h @@ -0,0 +1,83 @@ +/* + 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. +*/ + +#ifndef PICTURESWIDGET_H +#define PICTURESWIDGET_H + +#include <QWidget> +#include <QTreeView> +#include <QSqlDatabase> + +#include "smtreemodel.h" + +class PictureView; +class MappingTreeWidget; +class QSqlQuery; +class PicFilesModel; +class QSortFilterProxyModel; +class QHideEvent; +class QEvent; +class HoverWindow; + +class PicturesWidget : public QWidget { + Q_OBJECT + public: + explicit PicturesWidget(QWidget *parent = 0); + PictureView *picView() { return mPictureView; } + + private: + MappingTreeWidget *mMappingTree; + PictureView *mPictureView; +}; + +class PictureView : public QTreeView { + Q_OBJECT + public: + explicit PictureView(QWidget *parent = 0); + + public slots: + void mappingChanged(int mapping); + void deletePics(); + + protected: + virtual void hideEvent(QHideEvent *); + virtual bool event(QEvent *e); + virtual void contextMenuEvent(QContextMenuEvent *e); + + private: + HoverWindow *mHoverWin; + QModelIndex mCurHover; + QSortFilterProxyModel *mProxy; + PicFilesModel *mModel; + int mCursorOffset; +}; + +class PicFilesModel : public SmTreeModel { + Q_OBJECT + public: + enum Roles { FileNameRole = Qt::UserRole + 1, SizeRole = Qt::UserRole + 2, MimeTypeRole = Qt::UserRole + 3, FullPathRole = Qt::UserRole + 4, IdRole = Qt::UserRole + 5, AddedRole = Qt::UserRole + 6, Md5SumRole = Qt::UserRole + 7, SizeDisplayRole = Qt::UserRole + 8 }; + enum Fields { FileName = 0, Size = 1, MimeType = 2, FullPath = 3, Id = 4, Added = 5, Md5Sum = 6, SizeDisplay = 7 }; + enum { NumFields = 8 }; + explicit PicFilesModel(const QStringList &headers, QObject *parent = 0); + void setMapping(int mappingId) { mMappingId = mappingId; } + + //some data + Qt::ItemFlags flags(const QModelIndex &) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } + QVariant data(const QModelIndex &index, int role) const; + void removeFiles(const QList<QPersistentModelIndex> &files); + + public slots: + void populate(); + + private: + QSqlDatabase mDb; + QSqlQuery *mPopulateQ; + QSqlQuery *mDeleteFileQ; + int mMappingId; +}; + +#endif // PICTURESWIDGET_H @@ -55,6 +55,7 @@ #include "dbanalyzer.h" #include "mappingtreewidget.h" #include "newpicsdialog.h" +#include "pictureswidget.h" SheMov::SheMov(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags), mOpenWithGroupFS(0), mOpenWithGroupAV(0) { //application icon @@ -81,6 +82,10 @@ SheMov::SheMov(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, fla connect(mATree->seriesWidget()->seriesTree()->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(updateSelectionCount(QItemSelection,QItemSelection))); connect(this, SIGNAL(configChanged()), mATree, SLOT(readSettings())); + //pictures + mPicWidget = new PicturesWidget; + mTab->addTab(mPicWidget, tr("Pictures")); + //newmoviewizard + dbanalyzer mNewMovieWizard = new NewMovieWizard(this); connect(mNewMovieWizard, SIGNAL(seriesAdded(QString,int)), mATree->seriesWidget(), SLOT(seriesAdded(QString,int))); @@ -599,6 +604,11 @@ void SheMov::createActions(){ mSuggestFileA = new QAction(QIcon(":/analstretcher.png"), tr("Suggest file for burning"), this); connect(mSuggestFileA, SIGNAL(triggered()), mATree->filesWidget(), SLOT(suggest())); + //picture widget actions + mDeletePicFromA = new QAction(tr("Delete..."), this); + mPicWidget->picView()->addAction(mDeletePicFromA); + connect(mDeletePicFromA, SIGNAL(triggered()), mPicWidget->picView(), SLOT(deletePics())); + // misc mOpenWithMapperFS = new QSignalMapper(this); mOpenWithMapperAV = new QSignalMapper(this); @@ -24,6 +24,7 @@ class ArchiveTreeView; class NewMovieWizard; class DbAnalyzerDialog; class MappingTreeWidget; +class PicturesWidget; class SheMov : public QMainWindow { Q_OBJECT @@ -164,6 +165,10 @@ class SheMov : public QMainWindow { QActionGroup *mOpenWithGroupAV; QActionGroup *mFilesTreeHeadersGroup; QActionGroup *mEditGroup; + + //PictureWidget Actions + QAction *mDeletePicFromA; + QAction *mEditPicsAttrsA; //EndActions QSignalMapper *mRenameMapper; @@ -193,5 +198,6 @@ class SheMov : public QMainWindow { ArchiveTreeView *mATree; NewMovieWizard *mNewMovieWizard; DbAnalyzerDialog *mDbAnalyzerDialog; + PicturesWidget *mPicWidget; }; #endif @@ -38,7 +38,8 @@ SOURCES = main.cpp \ dbanalyzer.cpp \ mappingtreemodel.cpp \ mappingtreewidget.cpp \ - newpicsdialog.cpp + newpicsdialog.cpp \ + pictureswidget.cpp HEADERS = listitem.h \ filesystemdirproxy.h \ filesystemwidget.h \ @@ -72,6 +73,7 @@ HEADERS = listitem.h \ dbanalyzer.h \ mappingtreemodel.h \ mappingtreewidget.h \ - newpicsdialog.h + newpicsdialog.h \ + pictureswidget.h LIBS += -lmagic -lXfixes -lX11 RESOURCES = shemov.qrc |