]> Shamusworld >> Repos - virtualjaguar/blob - src/gui/filepicker.cpp
Added missing headers for win32, code cleanup for file detection code.
[virtualjaguar] / src / gui / filepicker.cpp
1 //
2 // filepicker.cpp - A ROM chooser
3 //
4 // by James L. Hammons
5 // (C) 2010 Underground Software
6 //
7 // JLH = James L. Hammons <jlhamm@acm.org>
8 //
9 // Who  When        What
10 // ---  ----------  -------------------------------------------------------------
11 // JLH  01/22/2010  Created this file
12 // JLH  02/06/2010  Modified to use Qt model/view framework
13 // JLH  03/08/2010  Added large cart view and info text
14 //
15
16 #include "filepicker.h"
17
18 #include "filedb.h"
19 #include "filelistmodel.h"
20 #include "filethread.h"
21 #include "imagedelegate.h"
22 //#include "settings.h"
23 //#include "types.h"
24
25 /*
26 Our strategy here is like so:
27 Look at the files in the directory pointed to by ROMPath.
28 For each file in the directory, take the CRC32 of it and compare it to the CRC
29 in the romList[]. If there's a match, put it in a list and note it's index value
30 in romList for future reference.
31
32 When constructing the list, use the index to pull up an image of the cart and
33 put that in the list. User picks from a graphical image of the cart.
34
35 Ideally, the label will go into the archive along with the ROM image, but that's
36 for the future...
37 Maybe box art, screenshots will go as well...
38
39 I'm thinking compatibility info should be displayed as well... Just to stop the
40 inevitable stupid questions from people too lazy to do basic research for themselves.
41
42
43 Data strategy:
44
45 - Should keep a QImage of the blank cart with blank label
46 - Should keep a QImage of the blank cart? (For overpainting the ROMs label)
47 - Should we have a special Alpine image? Floppy image (for COF/ABS)?
48
49 - Need some way of keeping track of cart size and compatibility info
50   [compat info needs to be BAD DUMP or % of what works]
51 - Need to properly scale the thumbnails images in the list
52 */
53
54 //could use Window as well...
55 //FilePickerWindow::FilePickerWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt::Dialog)
56 FilePickerWindow::FilePickerWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt::Window),
57         currentFile("")
58 {
59         setWindowTitle(tr("Insert Cartridge..."));
60
61 //is there any reason why this must be cast as a QAbstractListModel? No
62 //Also, need to think about data structure for the model...
63         model = new FileListModel;
64         fileList = new QListView;
65         fileList->setModel(model);
66 //      fileList->setItemDelegate(new ImageDelegate(this));
67         fileList->setItemDelegate(new ImageDelegate());
68 #if 0
69         //nope.
70 //      fileList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
71 //      fileList->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
72 //small problem with this is that it doesn't take scrollbar into account...
73 QSize sbSize = fileList->verticalScrollBar()->minimumSizeHint();
74 printf("VSB minimumSizeHint: %u, %u\n", sbSize.width(), sbSize.height());
75 QSize sbSize2 = fileList->verticalScrollBar()->sizeHint();
76 printf("VSB sizeHint: %u, %u\n", sbSize2.width(), sbSize2.height());
77 QRect sbRect = fileList->verticalScrollBar()->normalGeometry();
78 printf("VSB normalGeometry: %u, %u\n", sbRect.width(), sbRect.height());
79 QSize sbSize3 = fileList->verticalScrollBar()->size();
80 printf("VSB size: %u, %u\n", sbSize3.width(), sbSize3.height());
81 //      int sbWidth = fileList->verticalScrollBar()->width();
82         int sbWidth = fileList->verticalScrollBar()->size().width();
83         fileList->setFixedWidth((488/4) + 4 + sbWidth);//ick
84 #else
85         // This sets it to the "too large size" as the minimum!
86         QScrollBar * vsb = new QScrollBar(Qt::Vertical, this);
87         int sbWidth = vsb->size().width();
88         printf("VSB size width: %u\n", sbWidth);
89         int sbWidth2 = vsb->sizeHint().width();
90         printf("VSB sizeHint width: %u\n", sbWidth2);
91         delete vsb;
92
93 //      fileList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
94 //      fileList->verticalScrollBar()->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
95         fileList->setFixedWidth((488/4) + 4 + sbWidth);//ick
96 #endif
97
98 //      QVBoxLayout * layout = new QVBoxLayout;
99         QHBoxLayout * layout = new QHBoxLayout;
100         setLayout(layout);
101         layout->addWidget(fileList);
102
103         // Weird note: This layout has to be added *before* putting anything into it...
104         QVBoxLayout * vLayout = new QVBoxLayout;
105         layout->addLayout(vLayout);
106
107         cartImage = new QLabel;
108         QImage cartImg(":/res/cart-blank.png");
109         QPainter painter(&cartImg);
110         painter.drawPixmap(23, 87, QPixmap(":/res/label-blank.png"));
111         painter.end();
112         cartImage->setPixmap(QPixmap::fromImage(cartImg));
113         cartImage->setMargin(4);
114         vLayout->addWidget(cartImage);
115
116         title = new QLabel(QString(tr("<h2>...</h2>")));
117         title->setMargin(6);
118         title->setAlignment(Qt::AlignCenter);
119         vLayout->addWidget(title);
120
121 #if 1
122         QHBoxLayout * dataLayout = new QHBoxLayout;
123         vLayout->addLayout(dataLayout);
124
125         QLabel * labels = new QLabel(QString(tr(
126                 "<b>Type: </b><br>"
127                 "<b>CRC32: </b><br>"
128                 "<b>Compatibility: </b><br>"
129                 "<b>Notes:</b>"
130         )));
131         labels->setAlignment(Qt::AlignRight);
132         labels->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
133         dataLayout->addWidget(labels);
134         data = new QLabel(QString(tr(
135                 "4MB Cartridge<br>"
136                 "FEDCBA98<br>"
137                 "DOES NOT WORK<br>"
138                 "Universal Header detected; Requires DSP"
139         )));
140         data->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
141         dataLayout->addWidget(data);
142
143 //#warning "!!! Icon size for pushbutton is tiny !!!"
144         insertCart = new QPushButton(this);
145         insertCart->setIconSize(QSize(40, 40));
146         insertCart->setIcon(QIcon(":/res/insert.png"));
147         insertCart->setDefault(true);                           // We want this button to be the default
148         insertCart->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
149         dataLayout->addWidget(insertCart);
150 #else
151         QLabel * text2 = new QLabel(QString(tr(
152                 "<table>"
153                 "<tr><td align='right'><b>Type: </b></td><td>4MB Cartridge</td></tr>"
154                 "<tr><td align='right'><b>CRC32: </b></td><td>FEDCBA98</td></tr>"
155                 "<tr><td align='right'><b>Compatibility: </b></td><td>DOES NOT WORK</td></tr>"
156                 "<tr><td align='right'><b>Notes: </b></td><td>Universal Header detected; Requires DSP</td></tr>"
157                 "</table>"
158         )));
159         vLayout->addWidget(text2);
160 #endif
161
162         fileThread = new FileThread(this);
163 //      connect(fileThread, SIGNAL(FoundAFile(unsigned long)), this, SLOT(AddFileToList(unsigned long)));
164         connect(fileThread, SIGNAL(FoundAFile2(unsigned long, QString, QImage *, unsigned long)), this, SLOT(AddFileToList2(unsigned long, QString, QImage *, unsigned long)));
165         fileThread->Go();
166 /*
167 New sizes: 373x172 (label), 420x340 (cart)
168 */
169
170 //      QItemSelectionModel * ism = fileList->selectionModel();
171 //      connect(ism, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateSelection(const QModelIndex &, const QModelIndex &)));
172         connect(fileList->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateSelection(const QModelIndex &, const QModelIndex &)));
173
174         connect(insertCart, SIGNAL(clicked()), this, SLOT(LoadButtonPressed()));
175 }
176
177 QString FilePickerWindow::GetSelectedPrettyName(void)
178 {
179         return prettyFilename;
180 }
181
182 //
183 // This slot gets called by the FileThread's run() function when it finds a
184 // match in the filesystem to a ROM on our CRC list.
185 //
186 void FilePickerWindow::AddFileToList(unsigned long index)
187 {
188 printf("FilePickerWindow: Found match [%s]...\n", romList[index].name);
189         // NOTE: The model *ignores* what you send it, so this is crap. !!! FIX !!! [DONE, somewhat]
190 //      model->AddData(QIcon(":/res/generic.png"));
191 //      model->AddData(index);
192 }
193
194 void FilePickerWindow::AddFileToList2(unsigned long index, QString str, QImage * img, unsigned long size)
195 {
196 printf("FilePickerWindow(2): Found match [%s]...\n", romList[index].name);
197         if (img)
198         {
199                 model->AddData(index, str, *img, size);
200 //It would be better to pass the pointer into the model though...
201                 delete img;
202         }
203         else
204                 model->AddData(index, str, QImage(), size);
205 }
206
207 void FilePickerWindow::LoadButtonPressed(void)
208 {
209         // TODO: Get the text of the current selection, call the MainWin slot for loading
210         emit(RequestLoad(currentFile));
211         this->hide();
212 }
213
214 //
215 // This slot gets called when the QListView gets clicked on. Updates
216 // the cart graphic and accompanying text.
217 //
218 void FilePickerWindow::UpdateSelection(const QModelIndex & current, const QModelIndex &/*previous*/)
219 {
220 #if 0
221         QString s = current.model()->data(current, Qt::EditRole).toString();
222         unsigned long i = current.model()->data(current, Qt::DisplayRole).toUInt();
223         QImage label = current.model()->data(current, Qt::DecorationRole).value<QImage>();
224 //      printf("FPW: %s\n", s.toAscii().data());
225         unsigned long fileSize = current.model()->data(current, Qt::WhatsThisRole).toUInt();
226 #else
227 //      QString s = current.model()->data(current, FLM_FILENAME).toString();
228         currentFile = current.model()->data(current, FLM_FILENAME).toString();
229         unsigned long i = current.model()->data(current, FLM_INDEX).toUInt();
230         QImage label = current.model()->data(current, FLM_LABEL).value<QImage>();
231         unsigned long fileSize = current.model()->data(current, FLM_FILESIZE).toUInt();
232 //      printf("FPW: %s\n", s.toAscii().data());
233 #endif
234
235 //hm.
236 //currentFile = s;
237
238 //373x172 is label size...
239 //365x168 now...
240         if (!label.isNull())
241         {
242 /*
243         QImage cartImg(":/res/cart-blank.png");
244         QPainter painter(&cartImg);
245         painter.drawPixmap(23, 87, QPixmap(":/res/label-blank.png"));
246         painter.end();
247         cartSmall = cartImg.scaled(488/4, 395/4, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
248 */
249                 QImage cart(":/res/cart-blank.png");
250                 QPainter painter(&cart);
251 //Though this should probably be done when this is loaded, instead of every time here...
252 //QImage scaledImg = label.scaled(373, 172, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
253 //painter.drawPixmap(23, 87, QPixmap::fromImage(scaledImg));
254                 // Now, looks like it is...
255 //              painter.drawPixmap(23, 87, QPixmap::fromImage(label));
256                 painter.drawPixmap(27, 89, QPixmap::fromImage(label));
257 //              painter.drawPixmap(23, 87, 373, 172, QPixmap::fromImage(label));
258
259 // Well, heck. This should be done to the label *before* we get here.
260                 painter.drawPixmap(27, 89, QPixmap::fromImage(QImage(":/res/upper-left.png")));
261                 painter.drawPixmap(27+355, 89, QPixmap::fromImage(QImage(":/res/upper-right.png")));
262
263                 painter.end();
264                 cartImage->setPixmap(QPixmap::fromImage(cart));
265         }
266         else
267         {
268                 // We should try to be intelligent with our updates here, and only redraw when
269                 // we're going from a selection with a label to a selection without. Now, we
270                 // redraw regardless.
271 #if 0
272                 QImage cart(":/res/cart-blank.png");
273                 QPainter painter(&cart);
274 //              painter.drawPixmap(23, 87, QPixmap::fromImage(QImage(":/res/label-blank.png")));
275                 painter.drawPixmap(27, 89, QPixmap::fromImage(QImage(":/res/label-blank.png")));
276                 painter.end();
277 #else
278                 QImage cart;
279
280                 if (romList[i].flags & FF_ROM)
281                 {
282                         cart = QImage(":/res/cart-blank.png");
283                         QPainter painter(&cart);
284                         painter.drawPixmap(27, 89, QPixmap::fromImage(QImage(":/res/label-blank.png")));
285                         painter.end();
286                 }
287                 else if (romList[i].flags & FF_ALPINE)
288                 {
289                         cart = QImage(":/res/alpine-file.png");
290                 }
291                 else
292                         cart = QImage(":/res/unknown-file.png");
293 #endif
294                 cartImage->setPixmap(QPixmap::fromImage(cart));
295         }
296
297 //1048576
298 //2097152
299 //4194304
300         prettyFilename = romList[i].name;
301         title->setText(QString("<h2>%1</h2>").arg(romList[i].name));
302 //Kludge for now, we'll have to fix this later...
303 // So let's fix it now!
304         QString fileType;
305
306         if (romList[i].flags & FF_ROM)
307                 fileType = QString(tr("%1MB Cartridge")).arg(fileSize / 1048576);
308         else if (romList[i].flags & FF_ALPINE)
309                 fileType = QString(tr("%1MB Alpine ROM")).arg(fileSize / 1048576);
310         else
311                 fileType = QString(tr("*** UNKNOWN *** (%1 bytes)")).arg(fileSize);
312 //      QString fileType = QString(romList[i].flags & FF_ROM ? "%1MB Cartridge" : "%1*** UNKNOWN ***")
313 //              .arg(fileSize / 1048576);
314         QString crcString = QString("%1").arg(romList[i].crc32, 8, 16, QChar('0')).toUpper();
315         QString notes =
316 /*      (romList[i].flags & FF_ROM ? "Jaguar ROM " : "")*/
317                 QString(romList[i].flags & FF_BAD_DUMP ? "<b>BAD DUMP</b>" : "");
318         data->setText(QString("%1<br>%2<br>%3<br>%4").arg(fileType).arg(crcString).arg("???%").arg(notes));
319 }
320
321 /*
322     Super Duper Awesome Guy (World)
323
324          Type: 4MB Cartridge
325         CRC32: FEDCBA98
326 Compatibility: DOES NOT WORK
327         Notes: Universal Header detected; Requires DSP
328
329
330     Stupid Homebrew Game That Sux
331
332          Type: ABS/COF Executable (43853 bytes)
333         CRC32: 76543210
334 Compatibility: Unknown
335         Notes: $4000 Load, $4000 Run
336
337
338     Action Hopscotch Plus (Prototype)
339
340          Type: 2MB Alpine ROM
341         CRC32: 44889921
342 Compatibility: 80% (or ****)
343         Notes: EEPROM available
344 */