2 // filepicker.cpp - A ROM chooser
5 // (C) 2010 Underground Software
7 // JLH = James L. Hammons <jlhamm@acm.org>
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
16 #include "filepicker.h"
19 #include "filelistmodel.h"
20 #include "filethread.h"
21 #include "imagedelegate.h"
22 //#include "settings.h"
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.
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.
35 Ideally, the label will go into the archive along with the ROM image, but that's
37 Maybe box art, screenshots will go as well...
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.
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)?
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
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),
59 setWindowTitle(tr("Insert Cartridge..."));
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());
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
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);
93 // fileList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
94 // fileList->verticalScrollBar()->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
95 fileList->setFixedWidth((488/4) + 4 + sbWidth);//ick
98 // QVBoxLayout * layout = new QVBoxLayout;
99 QHBoxLayout * layout = new QHBoxLayout;
101 layout->addWidget(fileList);
103 // Weird note: This layout has to be added *before* putting anything into it...
104 QVBoxLayout * vLayout = new QVBoxLayout;
105 layout->addLayout(vLayout);
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"));
112 cartImage->setPixmap(QPixmap::fromImage(cartImg));
113 cartImage->setMargin(4);
114 vLayout->addWidget(cartImage);
116 title = new QLabel(QString(tr("<h2>...</h2>")));
118 title->setAlignment(Qt::AlignCenter);
119 vLayout->addWidget(title);
122 QHBoxLayout * dataLayout = new QHBoxLayout;
123 vLayout->addLayout(dataLayout);
125 QLabel * labels = new QLabel(QString(tr(
128 "<b>Compatibility: </b><br>"
131 labels->setAlignment(Qt::AlignRight);
132 labels->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
133 dataLayout->addWidget(labels);
134 data = new QLabel(QString(tr(
138 "Universal Header detected; Requires DSP"
140 data->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
141 dataLayout->addWidget(data);
143 insertCart = new QPushButton(QIcon(":/res/generic.png"), "", this);
144 insertCart->setDefault(true); // We want this button to be the default
145 insertCart->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
146 dataLayout->addWidget(insertCart);
148 QLabel * text2 = new QLabel(QString(tr(
150 "<tr><td align='right'><b>Type: </b></td><td>4MB Cartridge</td></tr>"
151 "<tr><td align='right'><b>CRC32: </b></td><td>FEDCBA98</td></tr>"
152 "<tr><td align='right'><b>Compatibility: </b></td><td>DOES NOT WORK</td></tr>"
153 "<tr><td align='right'><b>Notes: </b></td><td>Universal Header detected; Requires DSP</td></tr>"
156 vLayout->addWidget(text2);
159 fileThread = new FileThread(this);
160 // connect(fileThread, SIGNAL(FoundAFile(unsigned long)), this, SLOT(AddFileToList(unsigned long)));
161 connect(fileThread, SIGNAL(FoundAFile2(unsigned long, QString, QImage *, unsigned long)), this, SLOT(AddFileToList2(unsigned long, QString, QImage *, unsigned long)));
164 New sizes: 373x172 (label), 420x340 (cart)
167 // QItemSelectionModel * ism = fileList->selectionModel();
168 // connect(ism, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateSelection(const QModelIndex &, const QModelIndex &)));
169 connect(fileList->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateSelection(const QModelIndex &, const QModelIndex &)));
171 connect(insertCart, SIGNAL(clicked()), this, SLOT(LoadButtonPressed()));
175 // This slot gets called by the FileThread's run() function when it finds a
176 // match in the filesystem to a ROM on our CRC list.
178 void FilePickerWindow::AddFileToList(unsigned long index)
180 printf("FilePickerWindow: Found match [%s]...\n", romList[index].name);
181 // NOTE: The model *ignores* what you send it, so this is crap. !!! FIX !!! [DONE, somewhat]
182 // model->AddData(QIcon(":/res/generic.png"));
183 // model->AddData(index);
186 void FilePickerWindow::AddFileToList2(unsigned long index, QString str, QImage * img, unsigned long size)
188 printf("FilePickerWindow(2): Found match [%s]...\n", romList[index].name);
191 model->AddData(index, str, *img, size);
192 //It would be better to pass the pointer into the model though...
196 model->AddData(index, str, QImage(), size);
199 void FilePickerWindow::LoadButtonPressed(void)
201 // TODO: Get the text of the current selection, call the MainWin slot for loading
202 emit(RequestLoad(currentFile));
207 // This slot gets called when the QListView gets clicked on. Updates
208 // the cart graphic and accompanying text.
210 void FilePickerWindow::UpdateSelection(const QModelIndex & current, const QModelIndex &/*previous*/)
213 QString s = current.model()->data(current, Qt::EditRole).toString();
214 unsigned long i = current.model()->data(current, Qt::DisplayRole).toUInt();
215 QImage label = current.model()->data(current, Qt::DecorationRole).value<QImage>();
216 // printf("FPW: %s\n", s.toAscii().data());
217 unsigned long fileSize = current.model()->data(current, Qt::WhatsThisRole).toUInt();
219 // QString s = current.model()->data(current, FLM_FILENAME).toString();
220 currentFile = current.model()->data(current, FLM_FILENAME).toString();
221 unsigned long i = current.model()->data(current, FLM_INDEX).toUInt();
222 QImage label = current.model()->data(current, FLM_LABEL).value<QImage>();
223 unsigned long fileSize = current.model()->data(current, FLM_FILESIZE).toUInt();
224 // printf("FPW: %s\n", s.toAscii().data());
230 //373x172 is label size...
234 QImage cartImg(":/res/cart-blank.png");
235 QPainter painter(&cartImg);
236 painter.drawPixmap(23, 87, QPixmap(":/res/label-blank.png"));
238 cartSmall = cartImg.scaled(488/4, 395/4, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
240 QImage cart(":/res/cart-blank.png");
241 QPainter painter(&cart);
242 //Though this should probably be done when this is loaded, instead of every time here...
243 //QImage scaledImg = label.scaled(373, 172, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
244 //painter.drawPixmap(23, 87, QPixmap::fromImage(scaledImg));
245 // Now, looks like it is...
246 painter.drawPixmap(23, 87, QPixmap::fromImage(label));
247 // painter.drawPixmap(23, 87, 373, 172, QPixmap::fromImage(label));
249 cartImage->setPixmap(QPixmap::fromImage(cart));
253 // We should try to be intelligent with our updates here, and only redraw when
254 // we're going from a selection with a label to a selection without. Now, we
255 // redraw regardless.
256 QImage cart(":/res/cart-blank.png");
257 QPainter painter(&cart);
258 painter.drawPixmap(23, 87, QPixmap::fromImage(QImage(":/res/label-blank.png")));
260 cartImage->setPixmap(QPixmap::fromImage(cart));
266 title->setText(QString("<h2>%1</h2>").arg(romList[i].name));
267 //Kludge for now, we'll have to fix this later...
268 QString fileType = QString(romList[i].flags & FF_ROM ? "%1MB Cartridge" : "%1*** UNKNOWN ***")
269 .arg(fileSize / 1048576);
270 QString crcString = QString("%1").arg(romList[i].crc32, 8, 16, QChar('0')).toUpper();
272 /* (romList[i].flags & FF_ROM ? "Jaguar ROM " : "")*/
273 QString(romList[i].flags & FF_BAD_DUMP ? "<b>BAD DUMP</b>" : "");
274 data->setText(QString("%1<br>%2<br>%3<br>%4").arg(fileType).arg(crcString).arg("???%").arg(notes));
278 Super Duper Awesome Guy (World)
282 Compatibility: DOES NOT WORK
283 Notes: Universal Header detected; Requires DSP
286 Stupid Homebrew Game That Sux
288 Type: ABS/COF Executable (43853 bytes)
290 Compatibility: Unknown
291 Notes: $4000 Load, $4000 Run
294 Action Hopscotch Plus (Prototype)
298 Compatibility: 80% (or ****)
299 Notes: EEPROM available