diff options
author | am <am@f440f766-f032-0410-8965-dc7d17de2ca0> | 2009-07-17 17:36:23 +0000 |
---|---|---|
committer | am <am@f440f766-f032-0410-8965-dc7d17de2ca0> | 2009-07-17 17:36:23 +0000 |
commit | a477a1998c03bc0e7251463aff5486e3c0872d23 (patch) | |
tree | 1de3c2d32f1f1811a7dcc2058bfaf26c18f7e296 | |
parent | 1b1e48aa11c4518e100004dac594540e6024fa68 (diff) | |
download | SheMov-a477a1998c03bc0e7251463aff5486e3c0872d23.tar.gz SheMov-a477a1998c03bc0e7251463aff5486e3c0872d23.tar.bz2 SheMov-a477a1998c03bc0e7251463aff5486e3c0872d23.zip |
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
-rw-r--r-- | archive.svg | 139 | ||||
-rw-r--r-- | archiveeditwidget.cpp | 68 | ||||
-rw-r--r-- | archiveeditwidget.h | 37 | ||||
-rw-r--r-- | archivefilewidget.cpp | 192 | ||||
-rw-r--r-- | archivefilewidget.h | 65 | ||||
-rw-r--r-- | configurationdialog.cpp | 43 | ||||
-rw-r--r-- | configurationdialog.h | 4 | ||||
-rw-r--r-- | covereditor.cpp | 104 | ||||
-rw-r--r-- | covereditor.h | 35 | ||||
-rw-r--r-- | helper.cpp | 40 | ||||
-rw-r--r-- | helper.h | 1 | ||||
-rw-r--r-- | listeditor.cpp | 67 | ||||
-rw-r--r-- | listeditor.h | 40 | ||||
-rw-r--r-- | listmodel.cpp | 39 | ||||
-rw-r--r-- | listmodel.h | 1 | ||||
-rw-r--r-- | movieitem.cpp | 9 | ||||
-rw-r--r-- | moviemodel.cpp | 47 | ||||
-rw-r--r-- | shemov.cpp | 24 | ||||
-rw-r--r-- | shemov.h | 2 | ||||
-rw-r--r-- | shemov.png | bin | 0 -> 1812 bytes | |||
-rw-r--r-- | shemov.pro | 14 | ||||
-rw-r--r-- | shemov.qrc | 2 | ||||
-rw-r--r-- | shemoviconprovider.cpp | 3 |
23 files changed, 943 insertions, 33 deletions
diff --git a/archive.svg b/archive.svg new file mode 100644 index 0000000..39fc949 --- /dev/null +++ b/archive.svg @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg2383" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="archive.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs2385"> + <linearGradient + inkscape:collect="always" + id="linearGradient3263"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3265" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop3267" /> + </linearGradient> + <linearGradient + id="linearGradient3195"> + <stop + id="stop3235" + offset="0" + style="stop-color:#350feb;stop-opacity:0.89565217;" /> + <stop + style="stop-color:#aa0000;stop-opacity:0;" + offset="1" + id="stop3199" /> + </linearGradient> + <linearGradient + id="linearGradient3187"> + <stop + style="stop-color:#1fd31d;stop-opacity:1;" + offset="0" + id="stop3189" /> + <stop + style="stop-color:#fd161d;stop-opacity:0;" + offset="1" + id="stop3191" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 8 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="16 : 8 : 1" + inkscape:persp3d-origin="8 : 5.3333333 : 1" + id="perspective2391" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3195" + id="linearGradient3201" + x1="0.13069308" + y1="8.0712867" + x2="15.860396" + y2="8.0712867" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3263" + id="linearGradient3269" + x1="0.13069308" + y1="8.0712867" + x2="15.860396" + y2="8.0712867" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="22.197802" + inkscape:cx="6.305631" + inkscape:cy="15.207921" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1680" + inkscape:window-height="1028" + inkscape:window-x="1675" + inkscape:window-y="-3"> + <inkscape:grid + type="xygrid" + id="grid2393" /> + </sodipodi:namedview> + <metadata + id="metadata2388"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <rect + style="fill:url(#linearGradient3201);fill-opacity:1;stroke:url(#linearGradient3269);stroke-width:0.98890400000000001;stroke-opacity:1" + id="rect3183" + width="14.740799" + height="14.967531" + x="0.62514508" + y="0.58752114" + inkscape:transform-center-x="11.983168" + inkscape:transform-center-y="-0.45049505" /> + <text + xml:space="preserve" + style="font-size:16px;font-style:oblique;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#00007d;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold Oblique" + x="2.9921875" + y="13.832031" + id="text3271" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan3273" + x="2.9921875" + y="13.832031">A</tspan></text> + </g> +</svg> 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 <QSplitter> +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QLabel> + +#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 <QWidget> + +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 <QLabel> +#include <QTextEdit> +#include <QVBoxLayout> +#include <QHBoxLayout> +#include <QFont> +#include <QComboBox> +#include <QPushButton> +#include <QSpinBox> +#include <QColor> +#include <QLocale> +#include <QFileInfo> + +#include <QDebug> + +#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("<html><body><table><th><td>Filename</td><td>Size</td><td>MD5-Sum</td><td>Mime type</td></th>"); + 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("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td></tr>").arg(filename).arg(l.toString(size)).arg(md5).arg(mimeType); + mFiles->append(row); + mMd5Sums.insert(f, md5); + } + QString tableEnd("</table></body></html>"); + mFiles->append(tableEnd); +} + +const QList<int> ArchiveFileWidget::actorIds() const{ + QHash<QString, int>::const_iterator i = mActorIdMap.constBegin(); + QList<int> 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("<html><body><ul>"); + QHash<QString, int>::const_iterator i = mActorIdMap.constBegin(); + while(i != mActorIdMap.constEnd()){ + QString s = QString("<li>%1</li>").arg(i.key()); + mSelectedActors->append(s); + ++i; + } + mSelectedActors->append("</ul></body></html>"); +} + 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 <QWidget> +#include <QHash> +#include <QList> +#include <QLineEdit> + +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<int> 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<QString, QString> mMd5Sums; + QHash<QString, int> 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 <QComboBox> +#include <QStringList> +#include <QLabel> +#include <QGridLayout> + +#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 <QWidget> + +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 + @@ -7,6 +7,14 @@ #include <QString> #include <QByteArray> +#include <QFileInfo> +#include <QFile> + +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 +#include <md5.h> +#include <files.h> +#include <filters.h> +#include <hex.h> #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; + } } @@ -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 <QComboBox> +#include <QLineEdit> +#include <QPushButton> +#include <QHBoxLayout> +#include <QVBoxLayout> + +#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 <QWidget> + +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 <QString> #include <QSqlQuery> +#include <QSqlError> +#include <QDebug> + #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); @@ -16,19 +16,43 @@ #include <QItemSelection> #include <QSignalMapper> #include <QSettings> +#include <QMessageBox> +#include <QSqlDatabase> +#include <QSqlError> #include <QDebug> #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); @@ -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 Binary files differnew file mode 100644 index 0000000..8ce8258 --- /dev/null +++ b/shemov.png @@ -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 @@ -4,6 +4,8 @@ <file>movie.svg</file> <file>dildo.png</file> <file>picture.svg</file> + <file>shemov.png</file> + <file>archive.svg</file> </qresource> </RCC> 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); } |