summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArno <am@disconnect.de>2012-02-26 08:54:00 +0100
committerArno <am@disconnect.de>2012-02-26 08:54:00 +0100
commit7b373a2a860d1e779664fffe98db769be34d5591 (patch)
tree83369d25d97216023b7464b3b86b85450986114b
parent26530f47ff13e20d46472c12abc7567a61c14e57 (diff)
downloadSheMov-7b373a2a860d1e779664fffe98db769be34d5591.tar.gz
SheMov-7b373a2a860d1e779664fffe98db769be34d5591.tar.bz2
SheMov-7b373a2a860d1e779664fffe98db769be34d5591.zip
Implement PicturesWidget
Create a tab to show the archived pictures. It's far from complete, but it already does: * show pictures * hover * delete pictures from archive
-rw-r--r--mappingtreemodel.cpp1
-rw-r--r--mappingtreemodel.h1
-rw-r--r--mappingtreewidget.cpp8
-rw-r--r--mappingtreewidget.h4
-rw-r--r--pictureswidget.cpp228
-rw-r--r--pictureswidget.h83
-rw-r--r--shemov.cpp10
-rw-r--r--shemov.h6
-rw-r--r--shemov.pro6
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
diff --git a/shemov.cpp b/shemov.cpp
index 1006cab..30f7561 100644
--- a/shemov.cpp
+++ b/shemov.cpp
@@ -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);
diff --git a/shemov.h b/shemov.h
index f7a2f03..798d16c 100644
--- a/shemov.h
+++ b/shemov.h
@@ -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
diff --git a/shemov.pro b/shemov.pro
index 6e4d6d3..a7bb514 100644
--- a/shemov.pro
+++ b/shemov.pro
@@ -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