| 1 | // |
| 2 | // CartFilesListWin.cpp - List files in the cartridge |
| 3 | // |
| 4 | // by Jean-Paul Mari |
| 5 | // |
| 6 | // JPM = Jean-Paul Mari <djipi.mari@gmail.com> |
| 7 | // |
| 8 | // Who When What |
| 9 | // --- ---------- ----------------------------------------------------------- |
| 10 | // JPM Oct./2018 Created this file, and changed position of the status bar |
| 11 | // JPM Aug./2019 Update texts descriptions |
| 12 | // |
| 13 | |
| 14 | // TO DO: |
| 15 | // To allow file opening / viewing |
| 16 | // Remove/modify the 1st information, named '1', at the top |
| 17 | // To add a filter |
| 18 | // |
| 19 | |
| 20 | #include "debugger/CartFilesListWin.h" |
| 21 | #include "memory.h" |
| 22 | #include "settings.h" |
| 23 | #include "debugger/DBGManager.h" |
| 24 | |
| 25 | |
| 26 | // |
| 27 | CartFilesListWindow::CartFilesListWindow(QWidget * parent/*= 0*/) : QWidget(parent, Qt::Dialog), |
| 28 | TableView(new QTableView), |
| 29 | model(new QStandardItemModel), |
| 30 | TVlayout(new QVBoxLayout), |
| 31 | Mlayout(new QVBoxLayout), |
| 32 | layout(new QVBoxLayout), |
| 33 | treeView(new QTreeView), |
| 34 | standardModel(new QStandardItemModel), |
| 35 | rootNode(new QStandardItem), |
| 36 | CartDirectory(NULL), |
| 37 | TVstatusbar(new QStatusBar), |
| 38 | fileItems(NULL), |
| 39 | nbItem(0), |
| 40 | CartUsedBytes(0), |
| 41 | CartDirType(CFL_NOTYPE) |
| 42 | { |
| 43 | setWindowTitle(tr("cartridge directory & files")); |
| 44 | |
| 45 | // Set the font |
| 46 | QFont fixedFont("Lucida Console", 8, QFont::Normal); |
| 47 | fixedFont.setStyleHint(QFont::TypeWriter); |
| 48 | |
| 49 | // Set the new layout with proper identation and readibility |
| 50 | #ifdef CFL_BUFFERTREAM |
| 51 | model->setColumnCount(5); |
| 52 | #else |
| 53 | model->setColumnCount(4); |
| 54 | #endif |
| 55 | model->setHeaderData(0, Qt::Horizontal, QObject::tr("File")); |
| 56 | model->setHeaderData(1, Qt::Horizontal, QObject::tr("Address")); |
| 57 | model->setHeaderData(2, Qt::Horizontal, QObject::tr("Size")); |
| 58 | model->setHeaderData(3, Qt::Horizontal, QObject::tr("Seek")); |
| 59 | #ifdef CFL_BUFFERTREAM |
| 60 | model->setHeaderData(4, Qt::Horizontal, QObject::tr("Stream")); |
| 61 | #endif |
| 62 | // Information table |
| 63 | TableView->setModel(model); |
| 64 | TableView->setEditTriggers(QAbstractItemView::NoEditTriggers); |
| 65 | TableView->setShowGrid(0); |
| 66 | TableView->setFont(fixedFont); |
| 67 | TableView->verticalHeader()->setDefaultSectionSize(TableView->verticalHeader()->minimumSectionSize()); |
| 68 | TableView->verticalHeader()->setDefaultAlignment(Qt::AlignRight); |
| 69 | TVlayout->addWidget(TableView); |
| 70 | TVlayout->addWidget(TVstatusbar); |
| 71 | |
| 72 | // Setup root |
| 73 | rootNode = standardModel->invisibleRootItem(); |
| 74 | //register the model |
| 75 | treeView->setModel(standardModel); |
| 76 | treeView->expandAll(); |
| 77 | Mlayout->addWidget(treeView); |
| 78 | |
| 79 | // Set layouts |
| 80 | layout->addLayout(TVlayout); |
| 81 | layout->addLayout(Mlayout); |
| 82 | setLayout(layout); |
| 83 | } |
| 84 | |
| 85 | |
| 86 | // |
| 87 | CartFilesListWindow::~CartFilesListWindow(void) |
| 88 | { |
| 89 | } |
| 90 | |
| 91 | |
| 92 | // |
| 93 | void CartFilesListWindow::Reset(void) |
| 94 | { |
| 95 | standardModel->setRowCount(0); |
| 96 | model->setRowCount(0); |
| 97 | free(CartDirectory); |
| 98 | free(fileItems); |
| 99 | fileItems = NULL; |
| 100 | CartDirectory = NULL; |
| 101 | CartUsedBytes = CartNbrFiles = CartDirType = nbItem = 0; |
| 102 | } |
| 103 | |
| 104 | |
| 105 | // |
| 106 | void CartFilesListWindow::RefreshContents(void) |
| 107 | { |
| 108 | size_t Error; |
| 109 | char msg[1024]; |
| 110 | |
| 111 | if (isVisible()) |
| 112 | { |
| 113 | if (!CartDirectory) |
| 114 | { |
| 115 | if (CartDirType = GetDirType()) |
| 116 | { |
| 117 | if ((CartNbrFiles = GetNbrFiles())) |
| 118 | { |
| 119 | if ((CartDirectory = (CARTDIRINFO *)CreateInfos())) |
| 120 | { |
| 121 | UpdateInfos(); |
| 122 | sprintf(msg, "%u files | %u bytes in cartridge", (unsigned int)CartNbrFiles, (unsigned int)CartUsedBytes); |
| 123 | Error = CFL_NOERROR; |
| 124 | } |
| 125 | else |
| 126 | { |
| 127 | sprintf(msg, "Cannot use directory"); |
| 128 | Error = CFL_NODIRUSE; |
| 129 | } |
| 130 | } |
| 131 | else |
| 132 | { |
| 133 | sprintf(msg, "No files"); |
| 134 | Error = CFL_NOFILESLIST; |
| 135 | } |
| 136 | } |
| 137 | else |
| 138 | { |
| 139 | sprintf(msg, "No directory found"); |
| 140 | Error = CFL_NODIRECTORYLIST; |
| 141 | } |
| 142 | |
| 143 | // Display status bar |
| 144 | if (Error) |
| 145 | { |
| 146 | if ((Error & CFL_WARNING)) |
| 147 | { |
| 148 | TVstatusbar->setStyleSheet("background-color: lightyellow; font: bold"); |
| 149 | } |
| 150 | else |
| 151 | { |
| 152 | TVstatusbar->setStyleSheet("background-color: tomato; font: bold"); |
| 153 | } |
| 154 | } |
| 155 | else |
| 156 | { |
| 157 | TVstatusbar->setStyleSheet("background-color: lightgreen; font: bold"); |
| 158 | } |
| 159 | TVstatusbar->showMessage(QString(msg)); |
| 160 | } |
| 161 | else |
| 162 | { |
| 163 | UpdateInfos(); |
| 164 | } |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | |
| 169 | // Get files number in the cartridge directory |
| 170 | size_t CartFilesListWindow::GetNbrFiles(void) |
| 171 | { |
| 172 | switch (CartDirType) |
| 173 | { |
| 174 | case CFL_OSJAGTYPE: |
| 175 | return ((DBGManager_GetAdrFromSymbolName((char *)"OSJAG_Directory_End") - DBGManager_GetAdrFromSymbolName((char *)"OSJAG_Directory_Deb"))) / sizeof(long); |
| 176 | break; |
| 177 | |
| 178 | default: |
| 179 | return 0; |
| 180 | break; |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | |
| 185 | // Get cartridge directory type |
| 186 | size_t CartFilesListWindow::GetDirType(void) |
| 187 | { |
| 188 | if (DBGManager_GetAdrFromSymbolName((char *)"OSJAG_Directory")) |
| 189 | { |
| 190 | return CFL_OSJAGTYPE; |
| 191 | } |
| 192 | else |
| 193 | { |
| 194 | return CFL_NOTYPE; |
| 195 | } |
| 196 | } |
| 197 | |
| 198 | |
| 199 | // Get filename from index (starting from 0) |
| 200 | void CartFilesListWindow::GetFileInfos(CARTDIRINFO *Ptr, size_t index) |
| 201 | { |
| 202 | OSJAGDir *Adr; |
| 203 | size_t Offset; |
| 204 | |
| 205 | switch (CartDirType) |
| 206 | { |
| 207 | case CFL_OSJAGTYPE: |
| 208 | Offset = DBGManager_GetAdrFromSymbolName((char *)"OSJAG_Directory_Deb") + (index * sizeof(long)); |
| 209 | Adr = (OSJAGDir *)&jagMemSpace[Offset = GET32(jagMemSpace, Offset)]; |
| 210 | if (strlen(Adr->Filename)) |
| 211 | { |
| 212 | Ptr->PtrFilename = Adr->Filename; |
| 213 | Ptr->valid = true; |
| 214 | } |
| 215 | else |
| 216 | { |
| 217 | Ptr->PtrFilename = (char *)"(null)"; |
| 218 | } |
| 219 | Ptr->PtrDataFile = GET32(jagMemSpace, Offset); |
| 220 | Ptr->SizeFile = GET32(jagMemSpace, (Offset + sizeof(long))); |
| 221 | break; |
| 222 | |
| 223 | default: |
| 224 | break; |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | |
| 229 | // Create information from the cartridge directory information |
| 230 | void *CartFilesListWindow::CreateInfos(void) |
| 231 | { |
| 232 | CARTDIRINFO *Ptr = (CARTDIRINFO *)calloc(CartNbrFiles, sizeof(CARTDIRINFO)); |
| 233 | model->setRowCount(0); |
| 234 | |
| 235 | for (int i = 0; i < CartNbrFiles; i++) |
| 236 | { |
| 237 | GetFileInfos(&Ptr[i], i); |
| 238 | AddFilename(Ptr[i].PtrFilename, rootNode, 0); |
| 239 | // Display row content |
| 240 | model->insertRow(i); |
| 241 | model->setItem(i, 0, new QStandardItem(QString("%1").arg(Ptr[i].PtrFilename))); |
| 242 | if (Ptr[i].SizeFile) |
| 243 | { |
| 244 | model->setItem(i, 1, new QStandardItem(QString("0x%1").arg(Ptr[i].PtrDataFile, 6, 16, QChar('0')))); |
| 245 | model->setItem(i, 2, new QStandardItem(QString("0x%1").arg(Ptr[i].SizeFile, 6, 16, QChar('0')))); |
| 246 | } |
| 247 | CartUsedBytes += Ptr[i].SizeFile; |
| 248 | } |
| 249 | |
| 250 | return Ptr; |
| 251 | } |
| 252 | |
| 253 | |
| 254 | // Update the variables information (seek and stream buffer) |
| 255 | void CartFilesListWindow::UpdateInfos(void) |
| 256 | { |
| 257 | size_t Offset; |
| 258 | |
| 259 | for (int i = 0; i < CartNbrFiles; i++) |
| 260 | { |
| 261 | // Check if file validity (exitence) |
| 262 | if (CartDirectory[i].valid) |
| 263 | { |
| 264 | // Get the current seek and tentatively check validity (must be included in the ram zone) |
| 265 | Offset = DBGManager_GetAdrFromSymbolName((char *)"OSJAG_SeekPosition") + (i * sizeof(long)); |
| 266 | if ((CartDirectory[i].CurrentSeek = GET32(jagMemSpace, Offset)) < vjs.DRAM_size) |
| 267 | { |
| 268 | model->setItem(i, 3, new QStandardItem(QString("0x%1").arg(CartDirectory[i].CurrentSeek, 6, 16, QChar('0')))); |
| 269 | } |
| 270 | |
| 271 | // Get stream buffer address and check validity (must be included in the ram zone) |
| 272 | Offset = DBGManager_GetAdrFromSymbolName((char *)"OSJAG_PtrBuffer") + (i * sizeof(long)); |
| 273 | if (((CartDirectory[i].PtrBufferStream = GET32(jagMemSpace, Offset)) < vjs.DRAM_size) && CartDirectory[i].PtrBufferStream) |
| 274 | { |
| 275 | #ifdef CFL_BUFFERTREAM |
| 276 | model->setItem(i, 4, new QStandardItem(QString("0x%1").arg(CartDirectory[i].PtrBufferStream, 6, 16, QChar('0')))); |
| 277 | #else |
| 278 | if (!CartDirectory[i].SizeFile) |
| 279 | { |
| 280 | model->setItem(i, 1, new QStandardItem(QString("0x%1").arg(CartDirectory[i].PtrBufferStream, 6, 16, QChar('0')))); |
| 281 | } |
| 282 | #endif |
| 283 | } |
| 284 | else |
| 285 | { |
| 286 | #ifdef CFL_BUFFERTREAM |
| 287 | model->setItem(i, 4, new QStandardItem(QString("%1").arg(""))); |
| 288 | #else |
| 289 | if (!CartDirectory[i].SizeFile) |
| 290 | { |
| 291 | model->setItem(i, 1, new QStandardItem(QString("%1").arg(""))); |
| 292 | } |
| 293 | #endif |
| 294 | } |
| 295 | } |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | |
| 300 | // Add source code filename in the list |
| 301 | void CartFilesListWindow::AddFilename(char *FileName, QStandardItem *root, size_t ItemPos) |
| 302 | { |
| 303 | char *Ptr = FileName; |
| 304 | Sfileitem *PtrNewFile; |
| 305 | char Buffer[255]; |
| 306 | char a; |
| 307 | |
| 308 | while ((a = *Ptr++) && ((a != '\\') && (a != '/'))); |
| 309 | |
| 310 | if (a) |
| 311 | { |
| 312 | strncpy(Buffer, FileName, (Ptr - FileName - 1)); |
| 313 | Buffer[(Ptr - FileName - 1)] = 0; |
| 314 | } |
| 315 | else |
| 316 | { |
| 317 | strcpy(Buffer, FileName); |
| 318 | } |
| 319 | PtrNewFile = (Sfileitem *)AddItem(Buffer, ItemPos); |
| 320 | if (!PtrNewFile->PreviousItem) |
| 321 | { |
| 322 | PtrNewFile->PreviousItem = root; |
| 323 | root->appendRow(PtrNewFile->Item); |
| 324 | PtrNewFile->Item->setEditable(false); |
| 325 | } |
| 326 | |
| 327 | if (a) |
| 328 | { |
| 329 | return (AddFilename(Ptr, PtrNewFile->Item, (ItemPos + 1))); |
| 330 | } |
| 331 | } |
| 332 | |
| 333 | |
| 334 | // Add item to the list |
| 335 | // Return void * on new item or already existing one |
| 336 | void *CartFilesListWindow::AddItem(char *ItemName, size_t ItemPos) |
| 337 | { |
| 338 | Sfileitem *Ptr = fileItems; |
| 339 | |
| 340 | // Look for already existing item |
| 341 | for (size_t i = 0; i < nbItem; i++) |
| 342 | { |
| 343 | if ((Ptr->column == ItemPos) && !strcmp(Ptr->Item->text().toLocal8Bit().constData(), ItemName)) |
| 344 | { |
| 345 | return Ptr; |
| 346 | } |
| 347 | else |
| 348 | { |
| 349 | Ptr++; |
| 350 | } |
| 351 | } |
| 352 | |
| 353 | // Add item in the list |
| 354 | fileItems = (Sfileitem *)realloc(fileItems, (sizeof(Sfileitem) * ++nbItem)); |
| 355 | (fileItems + (nbItem - 1))->column = ItemPos; |
| 356 | (fileItems + (nbItem - 1))->PreviousItem = NULL; |
| 357 | (fileItems + (nbItem - 1))->Item = new QStandardItem(ItemName); |
| 358 | return (fileItems + (nbItem - 1)); |
| 359 | } |
| 360 | |
| 361 | |
| 362 | // |
| 363 | void CartFilesListWindow::keyPressEvent(QKeyEvent * e) |
| 364 | { |
| 365 | if (e->key() == Qt::Key_Escape) |
| 366 | { |
| 367 | hide(); |
| 368 | } |
| 369 | } |