]> Shamusworld >> Repos - virtualjaguar/blob - src/gui/filepicker.cpp
Fixed random crashes due to QImage corruption.
[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 {
58         setWindowTitle(tr("Insert Cartridge..."));
59
60 //is there any reason why this must be cast as a QAbstractListModel? No
61 //Also, need to think about data structure for the model...
62         model = new FileListModel;
63         fileList = new QListView;
64         fileList->setModel(model);
65 //      fileList->setItemDelegate(new ImageDelegate(this));
66         fileList->setItemDelegate(new ImageDelegate());
67 #if 0
68         //nope.
69 //      fileList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
70 //      fileList->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
71 //small problem with this is that it doesn't take scrollbar into account...
72 QSize sbSize = fileList->verticalScrollBar()->minimumSizeHint();
73 printf("VSB minimumSizeHint: %u, %u\n", sbSize.width(), sbSize.height());
74 QSize sbSize2 = fileList->verticalScrollBar()->sizeHint();
75 printf("VSB sizeHint: %u, %u\n", sbSize2.width(), sbSize2.height());
76 QRect sbRect = fileList->verticalScrollBar()->normalGeometry();
77 printf("VSB normalGeometry: %u, %u\n", sbRect.width(), sbRect.height());
78 QSize sbSize3 = fileList->verticalScrollBar()->size();
79 printf("VSB size: %u, %u\n", sbSize3.width(), sbSize3.height());
80 //      int sbWidth = fileList->verticalScrollBar()->width();
81         int sbWidth = fileList->verticalScrollBar()->size().width();
82         fileList->setFixedWidth((488/4) + 4 + sbWidth);//ick
83 #else
84         // This sets it to the "too large size" as the minimum!
85         QScrollBar * vsb = new QScrollBar(Qt::Vertical, this);
86         int sbWidth = vsb->size().width();
87         printf("VSB size width: %u\n", sbWidth);
88         int sbWidth2 = vsb->sizeHint().width();
89         printf("VSB sizeHint width: %u\n", sbWidth2);
90         delete vsb;
91
92 //      fileList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
93 //      fileList->verticalScrollBar()->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
94         fileList->setFixedWidth((488/4) + 4 + sbWidth);//ick
95 #endif
96
97 //      QVBoxLayout * layout = new QVBoxLayout;
98         QHBoxLayout * layout = new QHBoxLayout;
99         setLayout(layout);
100         layout->addWidget(fileList);
101
102         // Weird note: This layout has to be added *before* putting anything into it...
103         QVBoxLayout * vLayout = new QVBoxLayout;
104         layout->addLayout(vLayout);
105
106         cartImage = new QLabel;
107         QImage cartImg(":/res/cart-blank.png");
108         QPainter painter(&cartImg);
109         painter.drawPixmap(23, 87, QPixmap(":/res/label-blank.png"));
110         painter.end();
111         cartImage->setPixmap(QPixmap::fromImage(cartImg));
112         cartImage->setMargin(4);
113         vLayout->addWidget(cartImage);
114
115         title = new QLabel(QString(tr("<h2>...</h2>")));
116         title->setMargin(6);
117         title->setAlignment(Qt::AlignCenter);
118         vLayout->addWidget(title);
119
120 #if 1
121         QHBoxLayout * dataLayout = new QHBoxLayout;
122         vLayout->addLayout(dataLayout);
123
124         QLabel * labels = new QLabel(QString(tr(
125                 "<b>Type: </b><br>"
126                 "<b>CRC32: </b><br>"
127                 "<b>Compatibility: </b><br>"
128                 "<b>Notes:</b>"
129         )));
130         labels->setAlignment(Qt::AlignRight);
131         labels->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
132         dataLayout->addWidget(labels);
133         data = new QLabel(QString(tr(
134                 "4MB Cartridge<br>"
135                 "FEDCBA98<br>"
136                 "DOES NOT WORK<br>"
137                 "Universal Header detected; Requires DSP"
138         )));
139         data->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
140         dataLayout->addWidget(data);
141 #else
142         QLabel * text2 = new QLabel(QString(tr(
143                 "<table>"
144                 "<tr><td align='right'><b>Type: </b></td><td>4MB Cartridge</td></tr>"
145                 "<tr><td align='right'><b>CRC32: </b></td><td>FEDCBA98</td></tr>"
146                 "<tr><td align='right'><b>Compatibility: </b></td><td>DOES NOT WORK</td></tr>"
147                 "<tr><td align='right'><b>Notes: </b></td><td>Universal Header detected; Requires DSP</td></tr>"
148                 "</table>"
149         )));
150         vLayout->addWidget(text2);
151 #endif
152
153         fileThread = new FileThread(this);
154 //      connect(fileThread, SIGNAL(FoundAFile(unsigned long)), this, SLOT(AddFileToList(unsigned long)));
155         connect(fileThread, SIGNAL(FoundAFile2(unsigned long, QString, QImage *, unsigned long)), this, SLOT(AddFileToList2(unsigned long, QString, QImage *, unsigned long)));
156         fileThread->Go();
157 /*
158 New sizes: 373x172 (label), 420x340 (cart)
159 */
160
161 //      QItemSelectionModel * ism = fileList->selectionModel();
162 //      connect(ism, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateSelection(const QModelIndex &, const QModelIndex &)));
163         connect(fileList->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateSelection(const QModelIndex &, const QModelIndex &)));
164 }
165
166 //
167 // This slot gets called by the FileThread's run() function when it finds a
168 // match in the filesystem to a ROM on our CRC list.
169 //
170 void FilePickerWindow::AddFileToList(unsigned long index)
171 {
172 printf("FilePickerWindow: Found match [%s]...\n", romList[index].name);
173         // NOTE: The model *ignores* what you send it, so this is crap. !!! FIX !!! [DONE, somewhat]
174 //      model->AddData(QIcon(":/res/generic.png"));
175 //      model->AddData(index);
176 }
177
178 void FilePickerWindow::AddFileToList2(unsigned long index, QString str, QImage * img, unsigned long size)
179 {
180 printf("FilePickerWindow(2): Found match [%s]...\n", romList[index].name);
181         if (img)
182         {
183                 model->AddData(index, str, *img, size);
184 //It would be better to pass the pointer into the model though...
185                 delete img;
186         }
187         else
188                 model->AddData(index, str, QImage(), size);
189 }
190
191 //
192 // This slot gets called when the QListView gets clicked on. Updates
193 // the cart graphic and accompanying text.
194 //
195 void FilePickerWindow::UpdateSelection(const QModelIndex & current, const QModelIndex &/*previous*/)
196 {
197 #if 0
198         QString s = current.model()->data(current, Qt::EditRole).toString();
199         unsigned long i = current.model()->data(current, Qt::DisplayRole).toUInt();
200         QImage label = current.model()->data(current, Qt::DecorationRole).value<QImage>();
201 //      printf("FPW: %s\n", s.toAscii().data());
202         unsigned long fileSize = current.model()->data(current, Qt::WhatsThisRole).toUInt();
203 #else
204         QString s = current.model()->data(current, FLM_FILENAME).toString();
205         unsigned long i = current.model()->data(current, FLM_INDEX).toUInt();
206         QImage label = current.model()->data(current, FLM_LABEL).value<QImage>();
207         unsigned long fileSize = current.model()->data(current, FLM_FILESIZE).toUInt();
208 //      printf("FPW: %s\n", s.toAscii().data());
209 #endif
210 //373x172 is label size...
211         if (!label.isNull())
212         {
213 /*
214         QImage cartImg(":/res/cart-blank.png");
215         QPainter painter(&cartImg);
216         painter.drawPixmap(23, 87, QPixmap(":/res/label-blank.png"));
217         painter.end();
218         cartSmall = cartImg.scaled(488/4, 395/4, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
219 */
220                 QImage cart(":/res/cart-blank.png");
221                 QPainter painter(&cart);
222 //Though this should probably be done when this is loaded, instead of every time here...
223 //QImage scaledImg = label.scaled(373, 172, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
224 //painter.drawPixmap(23, 87, QPixmap::fromImage(scaledImg));
225                 painter.drawPixmap(23, 87, QPixmap::fromImage(label));
226 //              painter.drawPixmap(23, 87, 373, 172, QPixmap::fromImage(label));
227                 painter.end();
228                 cartImage->setPixmap(QPixmap::fromImage(cart));
229         }
230
231 //1048576
232 //2097152
233 //4194304
234         title->setText(QString("<h2>%1</h2>").arg(romList[i].name));
235 //Kludge for now, we'll have to fix this later...
236         QString fileType = QString(romList[i].flags & FF_ROM ? "%1MB Cartridge" : "%1*** UNKNOWN ***")
237                 .arg(fileSize / 1048576);
238         QString crcString = QString("%1").arg(romList[i].crc32, 8, 16, QChar('0')).toUpper();
239         QString notes =
240 /*      (romList[i].flags & FF_ROM ? "Jaguar ROM " : "")*/
241                 QString(romList[i].flags & FF_BAD_DUMP ? "<b>BAD DUMP</b>" : "");
242         data->setText(QString("%1<br>%2<br>%3<br>%4").arg(fileType).arg(crcString).arg("???%").arg(notes));
243 }
244
245 /*
246     Super Duper Awesome Guy (World)
247
248          Type: 4MB Cartridge
249         CRC32: FEDCBA98
250 Compatibility: DOES NOT WORK
251         Notes: Universal Header detected; Requires DSP
252
253
254     Stupid Homebrew Game That Sux
255
256          Type: ABS/COF Executable (43853 bytes)
257         CRC32: 76543210
258 Compatibility: Unknown
259         Notes: $4000 Load, $4000 Run
260
261
262     Action Hopscotch Plus (Prototype)
263
264          Type: 2MB Alpine ROM
265         CRC32: 44889921
266 Compatibility: 80% (or ****)
267         Notes: EEPROM available
268
269
270 */