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