From a477a1998c03bc0e7251463aff5486e3c0872d23 Mon Sep 17 00:00:00 2001 From: am Date: Fri, 17 Jul 2009 17:36:23 +0000 Subject: Huge changes: -Created an application icon and one for archives -implemented database configuration dialog -implemented listeditor -implemented covereditor -implemented md5sum helper -implemented archivefilewidget -Debugging spree: fixed SQL-statements and ListModel git-svn-id: file:///var/svn/repos2/shemov/trunk@389 f440f766-f032-0410-8965-dc7d17de2ca0 --- archive.svg | 139 +++++++++++++++++++++++++++++++++++ archiveeditwidget.cpp | 68 +++++++++++++++++ archiveeditwidget.h | 37 ++++++++++ archivefilewidget.cpp | 192 ++++++++++++++++++++++++++++++++++++++++++++++++ archivefilewidget.h | 65 ++++++++++++++++ configurationdialog.cpp | 43 ++++++++++- configurationdialog.h | 4 + covereditor.cpp | 104 ++++++++++++++++++++++++++ covereditor.h | 35 +++++++++ helper.cpp | 40 ++++++++++ helper.h | 1 + listeditor.cpp | 67 +++++++++++++++++ listeditor.h | 40 ++++++++++ listmodel.cpp | 39 ++++++---- listmodel.h | 1 + movieitem.cpp | 9 ++- moviemodel.cpp | 47 ++++++++---- shemov.cpp | 24 ++++++ shemov.h | 2 + shemov.png | Bin 0 -> 1812 bytes shemov.pro | 14 +++- shemov.qrc | 2 + shemoviconprovider.cpp | 3 + 23 files changed, 943 insertions(+), 33 deletions(-) create mode 100644 archive.svg create mode 100644 archiveeditwidget.cpp create mode 100644 archiveeditwidget.h create mode 100644 archivefilewidget.cpp create mode 100644 archivefilewidget.h create mode 100644 covereditor.cpp create mode 100644 covereditor.h create mode 100644 listeditor.cpp create mode 100644 listeditor.h create mode 100644 shemov.png diff --git a/archive.svg b/archive.svg new file mode 100644 index 0000000..39fc949 --- /dev/null +++ b/archive.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + A + + diff --git a/archiveeditwidget.cpp b/archiveeditwidget.cpp new file mode 100644 index 0000000..a404bc7 --- /dev/null +++ b/archiveeditwidget.cpp @@ -0,0 +1,68 @@ +/* + 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 "archiveeditwidget.h" +#include "archivefilewidget.h" +#include "listeditor.h" +#include "covereditor.h" +#include "listmodel.h" +#include "moviemodel.h" + +ArchiveEditWidget::ArchiveEditWidget(QWidget *parent) : QWidget(parent){ + //init models + mGenreModel = new ListModel("genre", this); + mActorsModel = new ListModel("actor", this); + mMovieModel = new MovieModel(this); + + QSplitter *hSplitter = new QSplitter(Qt::Horizontal); + QWidget *editorWidget = new QWidget; + QVBoxLayout *editorLayout = new QVBoxLayout; + + //genre editor + QLabel *l1 = new QLabel(tr("Edit genres")); + mGenreEditor = new ListEditor(mGenreModel); + editorLayout->addWidget(l1); + editorLayout->addWidget(mGenreEditor); + + //actor editor + QLabel *l2 = new QLabel(tr("Edit actors")); + mActorsEditor = new ListEditor(mActorsModel); + editorLayout->addWidget(l2); + editorLayout->addWidget(mActorsEditor); + + //cover editor + QLabel *l3 = new QLabel(tr("Configure cover pictures")); + mCoverEditor = new CoverEditor; + editorLayout->addWidget(l3); + editorLayout->addWidget(mCoverEditor); + + editorLayout->addStretch(); + editorWidget->setLayout(editorLayout); + + //archive editor + mFileWidget = new ArchiveFileWidget; + mFileWidget->setMovieModel(mMovieModel); + mFileWidget->setGenreModel(mGenreModel); + mFileWidget->setActorsModel(mActorsModel); + + //join splitters + hSplitter->addWidget(mFileWidget); + hSplitter->addWidget(editorWidget); + hSplitter->setStretchFactor(0, 2); + hSplitter->setStretchFactor(1, 1); + + QHBoxLayout *mainLayout = new QHBoxLayout; + mainLayout->addWidget(hSplitter); + + setLayout(mainLayout); + +} diff --git a/archiveeditwidget.h b/archiveeditwidget.h new file mode 100644 index 0000000..2f8b382 --- /dev/null +++ b/archiveeditwidget.h @@ -0,0 +1,37 @@ +/* + 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 ARCHIVEEDITWIDGET_H +#define ARCHIVEEDITWIDGET_H + +#include + +class ArchiveFileWidget; +class ListEditor; +class CoverEditor; +class ListModel; +class MovieModel; + +class ArchiveEditWidget : public QWidget { + Q_OBJECT + public: + ArchiveEditWidget(QWidget *parent = 0); + ~ArchiveEditWidget() {}; + + private: + ArchiveFileWidget *mFileWidget; + ListEditor *mGenreEditor; + ListEditor *mActorsEditor; + CoverEditor *mCoverEditor; + ListModel *mGenreModel; + ListModel *mActorsModel; + MovieModel *mMovieModel; + +}; + +#endif + diff --git a/archivefilewidget.cpp b/archivefilewidget.cpp new file mode 100644 index 0000000..8d7555c --- /dev/null +++ b/archivefilewidget.cpp @@ -0,0 +1,192 @@ +/* + 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 "archivefilewidget.h" +#include "moviemodel.h" +#include "listmodel.h" +#include "helper.h" + +ArchiveFileWidget::ArchiveFileWidget(MovieModel *model, QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) , mModel(model){ + QVBoxLayout *mainLayout = new QVBoxLayout; + + //selected files + QLabel *l1 = new QLabel(tr("Selected files:")); + mFiles = new QTextEdit; + mFiles->setReadOnly(true); + mFiles->setFont(QFont("Courier new")); + mFiles->setTextColor(QColor(Qt::red)); + mainLayout->addWidget(l1); + mainLayout->addWidget(mFiles); + + //genre combobox + QHBoxLayout *genreLayout = new QHBoxLayout; + QLabel *l2 = new QLabel(tr("Select genre")); + mGenre = new QComboBox; + genreLayout->addWidget(l2); + genreLayout->addWidget(mGenre); + mainLayout->addLayout(genreLayout); + + //actors combobox + QHBoxLayout *actorsLayout = new QHBoxLayout; + QLabel *l3 = new QLabel(tr("Select actors")); + mActors = new QComboBox; + actorsLayout->addWidget(l3); + actorsLayout->addWidget(mActors); + mainLayout->addLayout(actorsLayout); + + //selected actors + mSelectedActors = new QTextEdit; + mSelectedActors->setReadOnly(true); + mSelectedActors->setFont(QFont("Courier new")); + mSelectedActors->setTextColor(QColor(Qt::red)); + mainLayout->addWidget(mSelectedActors); + + //actors buttons + QHBoxLayout *actorButtonLayout = new QHBoxLayout; + mAddActor = new QPushButton(tr("&Add actor")); + connect(mAddActor, SIGNAL(clicked()), this, SLOT(addActor())); + mRemoveActor = new QPushButton(tr("&Remove actor")); + connect(mRemoveActor, SIGNAL(clicked()), this, SLOT(removeActor())); + actorButtonLayout->addStretch(); + actorButtonLayout->addWidget(mAddActor); + actorButtonLayout->addWidget(mRemoveActor); + mainLayout->addLayout(actorButtonLayout); + + //quality and movie title + QHBoxLayout *qualityTitleLayout = new QHBoxLayout; + QLabel *l4 = new QLabel(tr("Select quality")); + mQuality = new QSpinBox; + mQuality->setMinimum(0); + mQuality->setMaximum(10); + QLabel *l5 = new QLabel(tr("Set movie title")); + mTitle = new QLineEdit; + qualityTitleLayout->addWidget(l4); + qualityTitleLayout->addWidget(mQuality); + qualityTitleLayout->addWidget(l5); + qualityTitleLayout->addWidget(mTitle); + mainLayout->addLayout(qualityTitleLayout); + + //archive button layout + QHBoxLayout *archiveButtonLayout = new QHBoxLayout; + mArchive = new QPushButton(tr("Archive")); + connect(mArchive, SIGNAL(clicked()), this, SIGNAL(archive())); + archiveButtonLayout->addStretch(); + archiveButtonLayout->addWidget(mArchive); + mainLayout->addLayout(archiveButtonLayout); + + setLayout(mainLayout); +} + +void ArchiveFileWidget::setMovieModel(MovieModel *model){ + mModel = model; +} + +void ArchiveFileWidget::setGenreModel(ListModel *model){ + mGenreModel = model; + mGenre->setModel(mGenreModel); +} + +void ArchiveFileWidget::setActorsModel(ListModel *model){ + mActorsModel = model; + mActors->setModel(mActorsModel); +} + +void ArchiveFileWidget::setFiles(const QStringList &files){ + mFileList = files; + mFiles->clear(); + mMd5Sums.clear(); + mActorIdMap.clear(); + QString tableStart(""); + mFiles->append(tableStart); + QLocale l; + foreach(QString f, files){ + QFileInfo info(f); + qint64 size = info.size(); + QString md5 = Helper::md5Sum(f); + QString filename = info.fileName(); + QString mimeType = Helper::mimeType(f); + QString row = QString("").arg(filename).arg(l.toString(size)).arg(md5).arg(mimeType); + mFiles->append(row); + mMd5Sums.insert(f, md5); + } + QString tableEnd("
FilenameSizeMD5-SumMime type
%1%2%3%4
"); + mFiles->append(tableEnd); +} + +const QList ArchiveFileWidget::actorIds() const{ + QHash::const_iterator i = mActorIdMap.constBegin(); + QList retval; + while(i != mActorIdMap.constEnd()){ + retval << i.value(); + } + return retval; +} + +int ArchiveFileWidget::genreId() const{ + QString selectedGenre = mGenre->currentText(); + QModelIndex idx = mGenreModel->index(selectedGenre); + int retval(-1); + if(idx.isValid()){ + retval = mGenreModel->data(idx, ListModel::IdRole).toInt(); + }else{ + qDebug() << "genreId: invalid"; + } + return retval; +} + +void ArchiveFileWidget::addActor(){ + QString selectedActor = mActors->currentText(); + if(!selectedActor.isEmpty() && !mActorIdMap.contains(selectedActor)){ + QModelIndex idx = mActorsModel->index(selectedActor); + if(idx.isValid()){ + int id = mActorsModel->data(idx, ListModel::IdRole).toInt(); + mActorIdMap.insert(selectedActor, id); + createActorList(); + QString message = QString(tr("Added actor %1 to actor list")).arg(selectedActor); + emit statusbarMessage(message); + }else{ + qDebug() << "addActor: invalid!"; + } + } +} + +void ArchiveFileWidget::removeActor(){ + QString selectedActor = mActors->currentText(); + if(!selectedActor.isEmpty()){ + mActorIdMap.remove(selectedActor); + createActorList(); + QString message = QString(tr("Removed actor %1 from actor list")).arg(selectedActor); + emit statusbarMessage(message); + } +} + +void ArchiveFileWidget::createActorList(){ + mSelectedActors->clear(); + mSelectedActors->append("
    "); + QHash::const_iterator i = mActorIdMap.constBegin(); + while(i != mActorIdMap.constEnd()){ + QString s = QString("
  • %1
  • ").arg(i.key()); + mSelectedActors->append(s); + ++i; + } + mSelectedActors->append("
"); +} + diff --git a/archivefilewidget.h b/archivefilewidget.h new file mode 100644 index 0000000..8a9dbc9 --- /dev/null +++ b/archivefilewidget.h @@ -0,0 +1,65 @@ +/* + 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 ARCHIVEFILEWIDGET_H +#define ARCHIVEFILEWIDGET_H + +#include +#include +#include +#include + +class QTextEdit; +class QComboBox; +class QSpinBox; +class QPushButton; +class QStringList; +class MovieModel; +class ListModel; + +class ArchiveFileWidget : public QWidget { + Q_OBJECT + public: + ArchiveFileWidget(MovieModel *model = 0, QWidget *parent = 0, Qt::WindowFlags f = 0); + ~ArchiveFileWidget() {}; + void setMovieModel(MovieModel *model); + void setGenreModel(ListModel *model); + void setActorsModel(ListModel *model); + void setFiles(const QStringList &files); + const QList actorIds() const; + int genreId() const; + const QString movieTitle() const { return mTitle->text(); }; + + signals: + void statusbarMessage(const QString &message); + void archive(); + + private slots: + void addActor(); + void removeActor(); + + private: + void createActorList(); + MovieModel *mModel; + ListModel *mGenreModel; + ListModel *mActorsModel; + QTextEdit *mFiles; + QTextEdit *mSelectedActors; + QComboBox *mGenre; + QComboBox *mActors; + QPushButton *mAddActor; + QPushButton *mRemoveActor; + QPushButton *mArchive; + QSpinBox *mQuality; + QLineEdit *mTitle; + QStringList mFileList; + QHash mMd5Sums; + QHash mActorIdMap; +}; + +#endif + diff --git a/configurationdialog.cpp b/configurationdialog.cpp index 32fc197..065e105 100644 --- a/configurationdialog.cpp +++ b/configurationdialog.cpp @@ -41,7 +41,7 @@ ConfigurationDialog::ConfigurationDialog(QWidget *parent, Qt::WindowFlags f) : Q mPictureViewerArgs = new QLineEdit; pathGrid->addWidget(l2, 1, 0); pathGrid->addWidget(mPictureViewerArgs, 1, 1); - QLabel *l3 = new QLabel(tr("Path to &movie viewer")); + QLabel *l3 = new QLabel(tr("Path to movie viewer")); mMovieViewer = new QLineEdit; mMovieViewer->setCompleter(fsCompleter); l2->setBuddy(mMovieViewer); @@ -115,9 +115,38 @@ ConfigurationDialog::ConfigurationDialog(QWidget *parent, Qt::WindowFlags f) : Q expandButtons->addWidget(mAddExpandPath); expandButtons->addWidget(mRemoveExpandPath); uiGrid->addLayout(expandButtons, 4, 1); + uiGrid->addLayout(new QHBoxLayout, 5, 0, 2, 3); uiWidget->setLayout(uiGrid); mTab->addTab(uiWidget, tr("User interface")); + //database tab + QWidget *databaseWidget = new QWidget; + QGridLayout *dbGrid = new QGridLayout; + QLabel *dbl1 = new QLabel(tr("Database &host")); + mDatabaseHost = new QLineEdit; + dbl1->setBuddy(mDatabaseHost); + dbGrid->addWidget(dbl1, 0, 0); + dbGrid->addWidget(mDatabaseHost, 0, 1); + QLabel *dbl2 = new QLabel(tr("Database &name")); + mDatabaseName = new QLineEdit; + dbl2->setBuddy(mDatabaseName); + dbGrid->addWidget(dbl2, 1, 0); + dbGrid->addWidget(mDatabaseName, 1, 1); + QLabel *dbl3 = new QLabel(tr("Database &user")); + mDatabaseUsername = new QLineEdit; + dbl3->setBuddy(mDatabaseUsername); + dbGrid->addWidget(dbl3, 2, 0); + dbGrid->addWidget(mDatabaseUsername, 2, 1); + QLabel *dbl4 = new QLabel(tr("Database &password")); + mDatabasePassword = new QLineEdit; + dbl4->setBuddy(mDatabasePassword); + mDatabasePassword->setEchoMode(QLineEdit::Password); + dbGrid->addWidget(dbl4, 3, 0); + dbGrid->addWidget(mDatabasePassword, 3, 1); + dbGrid->addLayout(new QHBoxLayout, 4, 0, 2, 4); + databaseWidget->setLayout(dbGrid); + mTab->addTab(databaseWidget, tr("Database")); + //main layout mOk = new QPushButton(tr("Ok")); connect(mOk, SIGNAL(clicked()), this, SLOT(accept())); @@ -213,6 +242,12 @@ void ConfigurationDialog::readSettings(){ mIconForFolder->setCurrentIndex(pos); } + //read database + mDatabaseHost->setText(s.value("database/hostname").toString()); + mDatabaseName->setText(s.value("database/dbname").toString()); + mDatabaseUsername->setText(s.value("database/dbuser").toString()); + mDatabasePassword->setText(s.value("database/dbpass").toString()); + } void ConfigurationDialog::writeSettings(){ @@ -235,5 +270,11 @@ void ConfigurationDialog::writeSettings(){ s.setValue("ui/expandpaths", mEPaths); s.setValue("ui/folderIcon", mIconForFolder->currentText()); s.setValue("ui/selectstartup", mSelectStartup); + + //write database + s.setValue("database/hostname", mDatabaseHost->text()); + s.setValue("database/dbname", mDatabaseName->text()); + s.setValue("database/dbuser", mDatabaseUsername->text()); + s.setValue("database/dbpass", mDatabasePassword->text()); } diff --git a/configurationdialog.h b/configurationdialog.h index 3f28f5c..968b6f8 100644 --- a/configurationdialog.h +++ b/configurationdialog.h @@ -50,6 +50,10 @@ class ConfigurationDialog : public QDialog { QLineEdit *mArchiverArgs; QLineEdit *mExtractPath; QLineEdit *mExpandPath; + QLineEdit *mDatabaseHost; + QLineEdit *mDatabaseName; + QLineEdit *mDatabaseUsername; + QLineEdit *mDatabasePassword; QComboBox *mArchivePaths; QComboBox *mExpandPaths; QComboBox *mIconForFolder; diff --git a/covereditor.cpp b/covereditor.cpp new file mode 100644 index 0000000..13bd461 --- /dev/null +++ b/covereditor.cpp @@ -0,0 +1,104 @@ +/* + 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 "covereditor.h" + +CoverEditor::CoverEditor(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f){ + QGridLayout *mainLayout = new QGridLayout; + QLabel *l1 = new QLabel(tr("Front cover")); + mFrontCover = new QComboBox; + mainLayout->addWidget(l1, 0, 0); + mainLayout->addWidget(mFrontCover, 0, 1); + QLabel *l2 = new QLabel(tr("Back cover")); + mBackCover = new QComboBox; + mainLayout->addWidget(l2, 1, 0); + mainLayout->addWidget(mBackCover, 1, 1); + QLabel *l3 = new QLabel(tr("General cover")); + mCovers = new QComboBox; + mainLayout->addWidget(l3, 2, 0); + mainLayout->addWidget(mCovers, 2, 1); + setLayout(mainLayout); +} + +void CoverEditor::setCovers(const QStringList &covers){ + mCoverPaths = covers; + QStringList coverNames("-"); + QString front, back; + int idx(-1); + foreach(QString c, mCoverPaths){ + if((idx = c.lastIndexOf('/')) != -1){ + c.remove(0, idx); + } + if(c.toLower().contains("front")){ + front = c; + } + if(c.toLower().contains("back")){ + back = c; + } + coverNames << c; + } + mFrontCover->clear(); + mFrontCover->addItems(coverNames); + mBackCover->clear(); + mBackCover->addItems(coverNames); + mCovers->clear(); + mCovers->addItems(coverNames); + if(!front.isEmpty()){ + int idx = mFrontCover->findText(front); + if(idx != -1){ + mFrontCover->setCurrentIndex(idx); + } + } + if(!back.isEmpty()){ + int idx = mBackCover->findText(back); + if(idx != -1){ + mBackCover->setCurrentIndex(idx); + } + } +} + +const QString CoverEditor::frontCover() const{ + QString sel = mFrontCover->currentText(); + if(sel.isEmpty() || (sel == "-")){ + return QString(); + } + return findPath(sel); +} + +const QString CoverEditor::backCover() const{ + QString sel = mBackCover->currentText(); + if(sel.isEmpty() || (sel == "-")){ + return QString(); + } + return findPath(sel); +} + +const QString CoverEditor::covers() const{ + QString sel = mCovers->currentText(); + if(sel.isEmpty() || (sel == "-")){ + return QString(); + } + return findPath(sel); + +} + +const QString CoverEditor::findPath(const QString &name) const{ + QString retval; + foreach(QString s, mCoverPaths){ + if(s.endsWith(name)){ + retval = s; + break; + } + } + return retval; +} + diff --git a/covereditor.h b/covereditor.h new file mode 100644 index 0000000..39246cd --- /dev/null +++ b/covereditor.h @@ -0,0 +1,35 @@ +/* + 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 COVEREDITOR_H +#define COVEREDITOR_H + +#include + +class QComboBox; +class QStringList; + +class CoverEditor : public QWidget { + Q_OBJECT + public: + CoverEditor(QWidget *parent = 0, Qt::WindowFlags f = 0); + ~CoverEditor() {}; + void setCovers(const QStringList &covers); + const QString frontCover() const; + const QString backCover() const; + const QString covers() const; + + private: + const QString findPath(const QString &name) const; + QComboBox *mFrontCover; + QComboBox *mBackCover; + QComboBox *mCovers; + QStringList mCoverPaths; +}; + +#endif + diff --git a/helper.cpp b/helper.cpp index 116efa5..baaacbb 100644 --- a/helper.cpp +++ b/helper.cpp @@ -7,6 +7,14 @@ #include #include +#include +#include + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 +#include +#include +#include +#include #include "helper.h" @@ -35,5 +43,37 @@ namespace Helper { return retval; } } + + const QString md5Sum(const QString &path){ + QFileInfo info(path); + if(!info.exists() || !info.isFile()){ + return QString(); + } + + using namespace CryptoPP; + Weak::MD5 hash; + std::string res; + QString retval; + if(info.size() < (5 * 1024 * 1024)){ + FileSource f(qPrintable(path), true, new HashFilter(hash, new HexEncoder(new StringSink(res)))); + retval = QString::fromStdString(res).toLower(); + }else{ + QFile file(path); + file.open(QIODevice::ReadOnly); + int offset = info.size() / 3; + file.seek(offset); + int numBytes = 512 * 1024; + char *data = new char[numBytes]; + int read = file.read(data, numBytes); + if(read != numBytes){ + delete [] data; + return QString(); + } + StringSource s((byte*)data, numBytes, true, new HashFilter(hash, new HexEncoder(new StringSink(res)))); + retval = QString::fromStdString(res).toLower(); + delete [] data; + } + return retval; + } } diff --git a/helper.h b/helper.h index 033f7d6..642d566 100644 --- a/helper.h +++ b/helper.h @@ -14,6 +14,7 @@ class QString; namespace Helper { const QString mimeType(const QString &path); + const QString md5Sum(const QString &path); } #endif diff --git a/listeditor.cpp b/listeditor.cpp new file mode 100644 index 0000000..d3d2caf --- /dev/null +++ b/listeditor.cpp @@ -0,0 +1,67 @@ +/* + 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 "listeditor.h" +#include "listmodel.h" + +ListEditor::ListEditor(ListModel *model, QWidget *parent) : QWidget(parent), mModel(model){ + mItems = new QComboBox; + mItems->setModel(mModel); + + mEdit = new QLineEdit; + + mAdd = new QPushButton(tr("Add")); + connect(mAdd, SIGNAL(clicked()), this, SLOT(addItem())); + mRemove = new QPushButton(tr("Remove")); + connect(mRemove, SIGNAL(clicked()), this, SLOT(removeItem())); + mRename = new QPushButton(tr("Rename")); + connect(mRename, SIGNAL(clicked()), this, SLOT(renameItem())); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addWidget(mAdd); + buttonLayout->addWidget(mRemove); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(mItems); + mainLayout->addWidget(mEdit); + mainLayout->addLayout(buttonLayout); + + connect(mItems, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(itemChanged(const QString &))); + + setLayout(mainLayout); +} + +void ListEditor::addItem(){ + if(mEdit->text().isEmpty()){ + return; + } + QString newItem = mEdit->text().toLower(); + mModel->addItem(newItem); +} + +void ListEditor::removeItem(){ + mModel->removeItem(mItems->currentText()); +} + +void ListEditor::renameItem(){ + QString oldName = mItems->currentText(); + QString newName = mEdit->text(); + if(!newName.isEmpty()){ + mModel->renameItem(oldName, newName); + } +} + +void ListEditor::itemChanged(const QString &name){ + mEdit->setText(name); +} + diff --git a/listeditor.h b/listeditor.h new file mode 100644 index 0000000..a4f61fa --- /dev/null +++ b/listeditor.h @@ -0,0 +1,40 @@ +/* + 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 LISTEDITOR_H +#define LISTEDITOR_H + +#include + +class ListModel; +class QComboBox; +class QLineEdit; +class QPushButton; + +class ListEditor : public QWidget { + Q_OBJECT + public: + ListEditor(ListModel *model, QWidget *parent = 0); + ListEditor() {}; + + private slots: + void addItem(); + void removeItem(); + void renameItem(); + void itemChanged(const QString &name); + + private: + ListModel *mModel; + QComboBox *mItems; + QPushButton *mAdd; + QPushButton *mRemove; + QPushButton *mRename; + QLineEdit *mEdit; +}; + +#endif + diff --git a/listmodel.cpp b/listmodel.cpp index d8b6ccc..437ec3e 100644 --- a/listmodel.cpp +++ b/listmodel.cpp @@ -9,18 +9,25 @@ #include #include +#include +#include + #include "listmodel.h" #include "listitem.h" ListModel::ListModel(const QString table, QObject *parent) : QAbstractItemModel(parent), mTable(table){ QString updateQuery = QString("UPDATE %1 SET t%1name = :name WHERE i%1id = :id").arg(mTable); - mUpdateQuery = new QSqlQuery(updateQuery); - QString insertQuery = QString("INSERT INTO %1(t%1name) VALUES(:name)").arg(mTable); - mInsertQuery = new QSqlQuery(insertQuery); + mUpdateQuery = new QSqlQuery; + mUpdateQuery->prepare(updateQuery); + QString insertQuery = QString("INSERT INTO %1 (t%1name) VALUES(:name)").arg(mTable); + mInsertQuery = new QSqlQuery; + mInsertQuery->prepare(insertQuery); QString deleteQuery = QString("DELETE FROM %1 WHERE t%1name = :name").arg(mTable); - mDeleteQuery = new QSqlQuery(deleteQuery); + mDeleteQuery = new QSqlQuery; + mDeleteQuery->prepare(deleteQuery); QString idQuery = QString("SELECT i%1id FROM %1 WHERE t%1name = :name").arg(mTable); - mIdQuery = new QSqlQuery(idQuery); + mIdQuery = new QSqlQuery; + mIdQuery->prepare(idQuery); populate(); } @@ -29,13 +36,20 @@ ListModel::~ListModel(){ } QModelIndex ListModel::index(int row, int column, const QModelIndex &) const{ - if(column != 0){ + if((column != 0) || (row >= mItems.size()) || (row < 0)){ return QModelIndex(); } - if(row > mItems.size()){ - return QModelIndex(); + return createIndex(row, 0, mItems.at(row)); +} + +QModelIndex ListModel::index(const QVariant &data) const{ + for(int i = 0; i < rowCount(); ++i){ + ListItem *item = mItems.at(i); + if(data.toString() == item->name()){ + return createIndex(i, 0, item); + } } - return createIndex(row, 0); + return QModelIndex(); } int ListModel::rowCount(const QModelIndex &) const{ @@ -78,7 +92,7 @@ bool ListModel::removeRows(int row, int count, const QModelIndex&){ if(row > mItems.size()){ return false; } - if((row - count - mItems.size()) < 0){ + if((row + count) > rowCount()){ return false; } beginRemoveRows(QModelIndex(), row, row + (count - 1)); @@ -99,7 +113,7 @@ bool ListModel::setData(const QModelIndex &idx, const QVariant &data, int role){ Q_ASSERT(item != 0); int id = item->id(); bool success = false; - if(id == -1){ + if(id > -1){ //this is an update mUpdateQuery->bindValue(":id", id); success = mUpdateQuery->exec(); @@ -132,7 +146,7 @@ bool ListModel::addItem(const QVariant &item){ if(insertRows(0, 1, QModelIndex())){ QModelIndex idx = index(0, 0); if(idx.isValid()){ - success = setData(idx, item); + success = setData(idx, item, Qt::EditRole); } } return success; @@ -174,7 +188,6 @@ bool ListModel::renameItem(const QVariant &oldName, const QVariant &newName){ void ListModel::populate(){ QString query = QString("SELECT i%1id, t%1name FROM %1 ORDER BY t%1name").arg(mTable); QSqlQuery q(query); - q.exec(); while(q.next()){ ListItem *newItem = new ListItem(q.value(1).toString(), q.value(0).toInt()); mItems << newItem; diff --git a/listmodel.h b/listmodel.h index 1ecf10b..42f5ff5 100644 --- a/listmodel.h +++ b/listmodel.h @@ -24,6 +24,7 @@ class ListModel : public QAbstractItemModel { ListModel(const QString table, QObject *parent); ~ListModel(); QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex index(const QVariant &data) const; QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }; int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &) const { return 1; }; diff --git a/movieitem.cpp b/movieitem.cpp index b2fa545..9fb11e1 100644 --- a/movieitem.cpp +++ b/movieitem.cpp @@ -53,7 +53,8 @@ const QVariant MovieItem::dataAt(int column) const { } void MovieItem::populate(){ - QSqlQuery movieData("SELECT ttitle, tfilename, cmd5sum, bisize, igenreid, iquality, idvd FROM movies WHERE imovid = :id"); + QSqlQuery movieData; + movieData.prepare("SELECT ttitle, tfilename, cmd5sum, bisize, igenreid, iquality, idvd FROM movies WHERE imovid = :id"); movieData.bindValue(":id", mId); movieData.exec(); for(int i = 0; i < mNumRows; ++i){ @@ -65,7 +66,8 @@ void MovieItem::populate(){ void MovieItem::setGenreName(){ qint32 genreId = dataAt(Genre).toInt(); - QSqlQuery genreQuery("SELECT tgenrename FROM genre WHERE igenreid = :id"); + QSqlQuery genreQuery; + genreQuery.prepare("SELECT tgenrename FROM genre WHERE igenreid = :id"); genreQuery.bindValue(":id", genreId); genreQuery.exec(); while(genreQuery.next()){ @@ -74,7 +76,8 @@ void MovieItem::setGenreName(){ } void MovieItem::setActors(){ - QSqlQuery actorQuery("SELECT actor.tactorname FROM actors, actormoviemap WHERE actormoviemap.iactorid = actor.iactorid AND actormoviemap.imovid = :id"); + QSqlQuery actorQuery; + actorQuery.prepare("SELECT actor.tactorname FROM actor, movieactormap WHERE movieactormap.iactorid = actor.iactorid AND movieactormap.imovid = :id"); actorQuery.bindValue(":id", mId); actorQuery.exec(); while(actorQuery.next()){ diff --git a/moviemodel.cpp b/moviemodel.cpp index 9e6e493..3d93d41 100644 --- a/moviemodel.cpp +++ b/moviemodel.cpp @@ -12,19 +12,39 @@ MovieModel::MovieModel(QObject *parent) : QAbstractItemModel(parent) { mHeaders << tr("Title") << tr("Filename") << tr("MD5Sum") << tr("Size") << tr("Genre") << tr("Quality") << tr("Archived"); - mInsertQuery = new QSqlQuery("SELECT insert_movie(:title, :filename, :md5, :filesize, :genre, :quality, :dvd"); - mDeleteQuery = new QSqlQuery("DELETE FROM movies WHERE imovid = :id"); - mDeleteActorsForMovie = new QSqlQuery("DELETE FROM movieactormap WHERE imovid = :id"); - mInsertActorsForMovie = new QSqlQuery("INSERT INTO movieactormap VALUES(:movid, :actorid"); - mDeleteCovers = new QSqlQuery("DELETE FROM covers WHERE imovid = :id"); - mInsertCovers = new QSqlQuery("INSERT INTO covers VALUES(:filename, :movid, :covertype, :md5sum"); - mColumnQueries << new QSqlQuery("UPDATE movies SET ttitle = :value WHERE imovid = :id"); - mColumnQueries << new QSqlQuery("UPDATE movies SET tfilename = :value WHERE imovid = :id"); - mColumnQueries << new QSqlQuery("UPDATE movies SET cmd5sum = :value WHERE imovid = :id"); - mColumnQueries << new QSqlQuery("UPDATE movies SET bisize = :value WHERE imovid = :id"); - mColumnQueries << new QSqlQuery("UPDATE movies SET igenreid = :value WHERE imovid = :id"); - mColumnQueries << new QSqlQuery("UPDATE movies SET iquality = :value WHERE imovid = :id"); - mColumnQueries << new QSqlQuery("UPDATE movies SET idvd = :value WHERE imovid = :id"); + mInsertQuery = new QSqlQuery; + mInsertQuery->prepare("SELECT insert_movie(:title, :filename, :md5, :filesize, :genre, :quality, :dvd)"); + mDeleteQuery = new QSqlQuery; + mDeleteQuery->prepare("DELETE FROM movies WHERE imovid = :id"); + mDeleteActorsForMovie = new QSqlQuery; + mDeleteActorsForMovie->prepare("DELETE FROM movieactormap WHERE imovid = :id"); + mInsertActorsForMovie = new QSqlQuery; + mInsertActorsForMovie->prepare("INSERT INTO movieactormap VALUES(:movid, :actorid)"); + mDeleteCovers = new QSqlQuery; + mDeleteCovers->prepare("DELETE FROM covers WHERE imovid = :id"); + mInsertCovers = new QSqlQuery; + mInsertCovers->prepare("INSERT INTO covers VALUES(:filename, :movid, :covertype, :md5sum)"); + QSqlQuery *c1 = new QSqlQuery; + c1->prepare("UPDATE movies SET ttitle = :value WHERE imovid = :id"); + mColumnQueries << c1; + QSqlQuery *c2 = new QSqlQuery; + c2->prepare("UPDATE movies SET tfilename = :value WHERE imovid = :id"); + mColumnQueries << c2; + QSqlQuery *c3 = new QSqlQuery; + c3->prepare("UPDATE movies SET cmd5sum = :value WHERE imovid = :id"); + mColumnQueries << c3; + QSqlQuery *c4 = new QSqlQuery; + c4->prepare("UPDATE movies SET bisize = :value WHERE imovid = :id"); + mColumnQueries << c4; + QSqlQuery *c5 = new QSqlQuery; + c5->prepare("UPDATE movies SET igenreid = :value WHERE imovid = :id"); + mColumnQueries << c5; + QSqlQuery *c6 = new QSqlQuery; + c6->prepare("UPDATE movies SET iquality = :value WHERE imovid = :id"); + mColumnQueries << c6; + QSqlQuery *c7 = new QSqlQuery; + c7->prepare("UPDATE movies SET idvd = :value WHERE imovid = :id"); + mColumnQueries << c7; populate(); } @@ -204,7 +224,6 @@ void MovieModel::removeMovie(const QModelIndex &idx){ void MovieModel::populate(){ QSqlQuery movieQuery("SELECT imovid FROM movies"); - movieQuery.exec(); while(movieQuery.next()){ int id = movieQuery.value(0).toInt(); MovieItem *item = new MovieItem(id); diff --git a/shemov.cpp b/shemov.cpp index dfb16bd..0844cce 100644 --- a/shemov.cpp +++ b/shemov.cpp @@ -16,19 +16,43 @@ #include #include #include +#include +#include +#include #include #include "shemov.h" #include "filesystemwidget.h" #include "fileview.h" #include "configurationdialog.h" +#include "archiveeditwidget.h" SheMov::SheMov(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags) { + qApp->setWindowIcon(QIcon(":/shemov.png")); + + QSettings s; + QString dbhost = s.value("database/hostname").toString(); + QString dbname = s.value("database/dbname").toString(); + QString dbuser = s.value("database/dbuser").toString(); + QString dbpass = s.value("database/dbpass").toString(); + QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL"); + db.setHostName(dbhost); + db.setDatabaseName(dbname); + db.setUserName(dbuser); + db.setPassword(dbpass); + if(!db.open()){ + QMessageBox::critical(this, tr("Error"), tr("Could not open database. Please configure the database and restart the program")); + } + mFSWidget = new FilesystemWidget; setWindowTitle(mFSWidget->windowTitle()); + mAEWidget = new ArchiveEditWidget; mTab = new QTabWidget; mTab->addTab(mFSWidget, tr("Filemanager")); + mTab->addTab(mAEWidget, tr("Archive editor")); + + QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(mTab); diff --git a/shemov.h b/shemov.h index e9bedcf..52aa192 100644 --- a/shemov.h +++ b/shemov.h @@ -13,6 +13,7 @@ class QTabWidget; class FilesystemWidget; +class ArchiveEditWidget; class QAction; class QLabel; class QItemSelection; @@ -68,6 +69,7 @@ class SheMov : public QMainWindow { QTabWidget *mTab; FilesystemWidget *mFSWidget; + ArchiveEditWidget *mAEWidget; }; diff --git a/shemov.png b/shemov.png new file mode 100644 index 0000000..8ce8258 Binary files /dev/null and b/shemov.png differ diff --git a/shemov.pro b/shemov.pro index 786f1cb..8b4c196 100644 --- a/shemov.pro +++ b/shemov.pro @@ -16,7 +16,11 @@ helper.cpp \ shemoviconprovider.cpp \ messagedialog.cpp \ configurationdialog.cpp \ -extractordialog.cpp +extractordialog.cpp \ +archiveeditwidget.cpp \ +listeditor.cpp \ +covereditor.cpp \ +archivefilewidget.cpp HEADERS = listitem.h \ listmodel.h \ movieitem.h \ @@ -31,6 +35,12 @@ helper.h \ shemoviconprovider.h \ messagedialog.h \ configurationdialog.h \ -extractordialog.h +extractordialog.h \ +archiveeditwidget.h \ +listeditor.h \ +covereditor.h \ +archivefilewidget.h LIBS += -lmagic +LIBS += -lcryptopp +INCLUDEPATH += /usr/include/cryptopp RESOURCES = shemov.qrc diff --git a/shemov.qrc b/shemov.qrc index 9763baf..a533de8 100644 --- a/shemov.qrc +++ b/shemov.qrc @@ -4,6 +4,8 @@ movie.svg dildo.png picture.svg + shemov.png + archive.svg diff --git a/shemoviconprovider.cpp b/shemoviconprovider.cpp index daea4c0..569956c 100644 --- a/shemoviconprovider.cpp +++ b/shemoviconprovider.cpp @@ -29,6 +29,9 @@ QIcon SheMovIconProvider::icon(const QFileInfo &info) const { if(type.toLower().startsWith("image")){ return QIcon(":/picture.svg"); } + if(type.toLower().contains("application/x-rar")){ + return QIcon(":/archive.svg"); + } return QFileIconProvider::icon(info); } -- cgit v1.2.3-70-g09d2