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 //#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);
151 QLabel * text2 = new QLabel(QString(tr(
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>"
159 vLayout->addWidget(text2);
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)));
167 New sizes: 373x172 (label), 420x340 (cart)
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 &)));
174 connect(insertCart, SIGNAL(clicked()), this, SLOT(LoadButtonPressed()));
177 QString FilePickerWindow::GetSelectedPrettyName(void)
179 return prettyFilename;
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.
186 void FilePickerWindow::AddFileToList(unsigned long index)
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);
194 void FilePickerWindow::AddFileToList2(unsigned long index, QString str, QImage * img, unsigned long size)
196 printf("FilePickerWindow(2): Found match [%s]...\n", romList[index].name);
199 model->AddData(index, str, *img, size);
200 //It would be better to pass the pointer into the model though...
204 model->AddData(index, str, QImage(), size);
207 void FilePickerWindow::LoadButtonPressed(void)
209 // TODO: Get the text of the current selection, call the MainWin slot for loading
210 emit(RequestLoad(currentFile));
215 // This slot gets called when the QListView gets clicked on. Updates
216 // the cart graphic and accompanying text.
218 void FilePickerWindow::UpdateSelection(const QModelIndex & current, const QModelIndex &/*previous*/)
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();
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());
238 //373x172 is label size...
243 QImage cartImg(":/res/cart-blank.png");
244 QPainter painter(&cartImg);
245 painter.drawPixmap(23, 87, QPixmap(":/res/label-blank.png"));
247 cartSmall = cartImg.scaled(488/4, 395/4, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
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));
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")));
264 cartImage->setPixmap(QPixmap::fromImage(cart));
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 QImage cart(":/res/cart-blank.png");
272 QPainter painter(&cart);
273 // painter.drawPixmap(23, 87, QPixmap::fromImage(QImage(":/res/label-blank.png")));
274 painter.drawPixmap(27, 89, QPixmap::fromImage(QImage(":/res/label-blank.png")));
276 cartImage->setPixmap(QPixmap::fromImage(cart));
282 prettyFilename = romList[i].name;
283 title->setText(QString("<h2>%1</h2>").arg(romList[i].name));
284 //Kludge for now, we'll have to fix this later...
285 QString fileType = QString(romList[i].flags & FF_ROM ? "%1MB Cartridge" : "%1*** UNKNOWN ***")
286 .arg(fileSize / 1048576);
287 QString crcString = QString("%1").arg(romList[i].crc32, 8, 16, QChar('0')).toUpper();
289 /* (romList[i].flags & FF_ROM ? "Jaguar ROM " : "")*/
290 QString(romList[i].flags & FF_BAD_DUMP ? "<b>BAD DUMP</b>" : "");
291 data->setText(QString("%1<br>%2<br>%3<br>%4").arg(fileType).arg(crcString).arg("???%").arg(notes));
295 Super Duper Awesome Guy (World)
299 Compatibility: DOES NOT WORK
300 Notes: Universal Header detected; Requires DSP
303 Stupid Homebrew Game That Sux
305 Type: ABS/COF Executable (43853 bytes)
307 Compatibility: Unknown
308 Notes: $4000 Load, $4000 Run
311 Action Hopscotch Plus (Prototype)
315 Compatibility: 80% (or ****)
316 Notes: EEPROM available