-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmainwindow.cpp
More file actions
248 lines (236 loc) · 8.75 KB
/
mainwindow.cpp
File metadata and controls
248 lines (236 loc) · 8.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QDebug"
#include "QFileDialog"
#include "QFileInfo"
#include "QMessageBox"
#include "QProgressDialog"
#include "QtSql/QSqlDriver"
#include "QtSql/QSqlDatabase"
#include "QtSql/QSqlError"
#include "QtSql/QSqlQuery"
#include "QThread"
const QList<QString> QLIST_DB_FIELD_NAMES = { "id", "account_id", "guid", "rating",
"view_offset", "view_count", "last_viewed_at",
"created_at", "updated_at", "skip_count",
"last_skipped_at", "changed_at", "extra_data",
"last_rated_at" };
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
bool MainWindow::createDBConnection(QString dbFile)
{
bool success = false;
if (dbFile.isEmpty() == false)
{
// check if dbFile is an existant file
if (QFileInfo::exists(dbFile) && QFileInfo(dbFile).isFile())
{
// dbFile exists and is a file (not a directory) so attempt to db connection to it
qDebug() << "source:" << ui->leSource->text();
// for some reason, the addDatabase call has to be a static call on the next line
qsqlDB = QSqlDatabase::addDatabase("QSQLITE");
qsqlDB.setDatabaseName(dbFile);
bool success = qsqlDB.open();
qDebug() << "db connection was:" << success;
return success;
}
}
else
{
// dbFile argument passed was empty
qDebug() << "Argument dbFile was empty: '" << dbFile <<"'";
}
return success;
}
void MainWindow::on_btnSource_clicked()
{
QString qstrSource = QFileDialog::getOpenFileName(this,
tr("Select Source file..."), QDir::toNativeSeparators(QDir::homePath()), tr("Plex Database File (*.plugins.library.db*);;Any File (*.*)"));
ui->leSource->setText(qstrSource);
qDebug() << "qstrSource:" << qstrSource;
}
void MainWindow::on_btnDest_clicked()
{
// dev-note: QFileDialog::getSaveFileName can be used to 'select' a non-existant file using a standard file selection dialog
// reference: https://stackoverflow.com/questions/29907625/qfiledialog-using-getopenfilename-allow-for-non-existent-files/29907690#29907690
QString qstrDest = QFileDialog::getSaveFileName(this,
tr("Select Destination file..."),
QDir::toNativeSeparators(QDir::homePath()),
tr("Plex Database File (*.plugins.library.db*);;Any File (*.*)"),
nullptr,
QFileDialog::DontConfirmOverwrite);
ui->leDest->setText(qstrDest);
qDebug() << "qstrDest:" << qstrDest;
}
void MainWindow::on_btnLaunch_clicked()
{
// check the value of ui->coboAction and act accordingly
if (ui->coboAction->currentText() == "Export from Source to Destination")
{
// exporting from database, attempt connection
if (MainWindow::createDBConnection(ui->leSource->text()))
{
int iRowsTotal = 0;
QSqlQuery query;
query.prepare("SELECT * FROM metadata_item_settings");
if (query.exec())
{
QFile qfileOutFile(ui->leDest->text());
if (qfileOutFile.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream qtstOut(&qfileOutFile);
qDebug() << "db query succeeded, numRowsAffected:" << query.numRowsAffected();
// loop through the database query results
query.first();
do
{
bool okCheck;
iRowsTotal++;
QString o = "INSERT OR REPLACE INTO metadata_item_settings VALUES (";
// loop through the fieldNames
for (int i = 0; i < QLIST_DB_FIELD_NAMES.size(); ++i)
{
QString qstrFieldValue = query.value(i).toString();
if (qstrFieldValue.toInt(&okCheck, 10))
{
o.append(qstrFieldValue + ", ");
}
else if (qstrFieldValue.isEmpty())
{
o.append("NULL, ");
}
else
{
o.append("'" + qstrFieldValue + "', ");
}
}
o.chop(2);
o.append(");");
qtstOut << o << "\n";
} while (query.next());
qfileOutFile.close();
QString qstrCompleteMsg = "Total records exported: " + QString::number(iRowsTotal);
// the qbytearray is used to cast the QString to a char string so that we can use it in the tr() call for the QMessageBox
QByteArray ba = qstrCompleteMsg.toLocal8Bit();
const char *cstrCompleteMsg = ba.data();
QMessageBox::information(this, tr("Export Complete"),
tr(cstrCompleteMsg),
QMessageBox::Ok);
}
else
{
qDebug() << "Oops! Could not open output file '" << ui->leDest->text() << "' for writing.";
QMessageBox::warning( this,
tr("Open file failed"),
tr("Unable to open the destination file for writing.<br/>Please check the file's permissions or existence."),
QMessageBox::Ok);
}
}
else
{
qDebug() << "db query failed, error was: " << query.lastError();
QMessageBox::warning( this,
tr("Database query failed"),
tr("Query to the SQLite database failed. No data could be read from the database file so there's nothing to export.<br/>Please check the file's permissions, format or existence."),
QMessageBox::Ok);
}
qDebug() << "Total Rows Processed:" << iRowsTotal;
}
else
{
// database connection failed - should prolly let the user nkow about that?
QMessageBox::warning( this,
tr("Database connection failed"),
tr("Unable to connect to the SQLite database.<br/>Please check the file's permissions, format or existence."),
QMessageBox::Ok);
}
}
else if (ui->coboAction->currentText() == "Import from Source to Destination")
{
// importing from database, attempt connection
if (MainWindow::createDBConnection(ui->leDest->text()))
{
int iRowsTotal = 0;
int iRowsOK = 0;
int iRowsFail = 0;
QSqlQuery query = QSqlQuery(qsqlDB);
QFile qfileInFile(ui->leSource->text());
qint64 filesize = qfileInFile.size();
int readBytes = 0;
// open the sourceFile and loop it, pushing contents into destFile
if (qfileInFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
QByteArray line;
QProgressDialog progress("Importing data...", "Cancel", 0, 100, this);
progress.setWindowModality(Qt::WindowModal);
while (!qfileInFile.atEnd())
{
iRowsTotal++;
line = qfileInFile.readLine();
readBytes += line.length();
qDebug() << "Query: " + line;
query.prepare(line);
if (query.exec(line))
{
iRowsOK++;
}
else
{
iRowsFail++;
qDebug() << query.lastError();
}
progress.setValue((int)((readBytes * 100) / filesize));
if (progress.wasCanceled())
break;
}
QString qstrCompleteMsg = "Total lines processed: " + QString::number(iRowsTotal) + "\n" +
"Records imported: " + QString::number(iRowsOK) + "\n" +
"Lines failed: " + QString::number(iRowsFail);
// the qbytearray is used to cast the QString to a char string so that we can use it in the tr() call for the QMessageBox
QByteArray ba = qstrCompleteMsg.toLocal8Bit();
const char *cstrCompleteMsg = ba.data();
QMessageBox::information(this, tr("Import Complete"),
tr(cstrCompleteMsg),
QMessageBox::Ok);
}
else
{
// file open for reading failed - should prolly let user know about that?
QMessageBox::warning( this,
tr("Open file failed"),
tr("Unable to open the source file.<br/>Please check the file's permissions, format or existence."),
QMessageBox::Ok);
}
}
else
{
// database connection failed - should prolly let the user nkow about that?
QMessageBox::warning( this,
tr("Database connection failed"),
tr("Unable to connect to the SQLite database.<br/>Please check the file's permissions, format or existence."),
QMessageBox::Ok);
}
}
else
{
// this should never happen unless there is a bug
qDebug() << "some how this happened... ???";
}
qsqlDB.close();
}
void MainWindow::on_actionAbout_triggered()
{
QMessageBox::about(this, "PMSIE::About", "PMSIE is a small utility to export/import watched media metadata from/to Plex Media Server's database.<br/><br/>Written by Cabji, 2020.<br/><br/><a href=\"https://github.com/Cabji/qtPMSIE\">https://github.com/Cabji/qtPMSIE</a><br/><br/>Free for all, provided as is, no warranty or liability.");
}
void MainWindow::on_actionHelp_triggered()
{
QMessageBox::about(this, "PMSIE::Help", "For help, please see <a href=\"http://www.github.com/Cabji/qtPMSIE/help\">PMSIE Help Online</a>.");
}