"Fossies" - the Fresh Open Source Software Archive

Member "cutter-1.8.2/src/dialogs/NewFileDialog.cpp" (20 May 2019, 11763 Bytes) of package /linux/privat/cutter-1.8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "NewFileDialog.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.8.1_vs_1.8.2.

    1 #include "InitialOptionsDialog.h"
    2 #include "core/MainWindow.h"
    3 #include "dialogs/NewFileDialog.h"
    4 #include "dialogs/AboutDialog.h"
    5 #include "ui_NewfileDialog.h"
    6 #include "common/Helpers.h"
    7 #include "common/HighDpiPixmap.h"
    8 
    9 #include <QFileDialog>
   10 #include <QtGui>
   11 #include <QMessageBox>
   12 #include <QDir>
   13 #include <QPushButton>
   14 #include <QLineEdit>
   15 
   16 const int NewFileDialog::MaxRecentFiles;
   17 
   18 static QColor getColorFor(int pos)
   19 {
   20     static const QList<QColor> colors = {
   21         QColor(29, 188, 156), // Turquoise
   22         QColor(52, 152, 219), // Blue
   23         QColor(155, 89, 182), // Violet
   24         QColor(52, 73, 94),   // Grey
   25         QColor(231, 76, 60),  // Red
   26         QColor(243, 156, 17)  // Orange
   27     };
   28     return colors[pos % 6];
   29 }
   30 
   31 static QIcon getIconFor(const QString &str, int pos)
   32 {
   33     // Add to the icon list
   34     int w = 64;
   35     int h = 64;
   36 
   37     HighDpiPixmap pixmap(w, h);
   38     pixmap.fill(Qt::transparent);
   39 
   40     QPainter pixPaint(&pixmap);
   41     pixPaint.setPen(Qt::NoPen);
   42     pixPaint.setRenderHint(QPainter::Antialiasing);
   43     pixPaint.setBrush(getColorFor(pos));
   44     pixPaint.drawEllipse(1, 1, w - 2, h - 2);
   45     pixPaint.setPen(Qt::white);
   46     pixPaint.setFont(QFont("Verdana", 24, 1));
   47     pixPaint.drawText(0, 0, w, h - 2, Qt::AlignCenter, QString(str).toUpper().mid(0, 2));
   48     return QIcon(pixmap);
   49 }
   50 
   51 NewFileDialog::NewFileDialog(MainWindow *main) :
   52     QDialog(nullptr), // no parent on purpose, using main causes weird positioning
   53     ui(new Ui::NewFileDialog),
   54     main(main)
   55 {
   56     ui->setupUi(this);
   57     setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
   58     setAcceptDrops(true);
   59     ui->recentsListWidget->addAction(ui->actionRemove_item);
   60     ui->recentsListWidget->addAction(ui->actionClear_all);
   61     ui->projectsListWidget->addAction(ui->actionRemove_project);
   62     ui->logoSvgWidget->load(Config()->getLogoFile());
   63 
   64     // radare2 does not seem to save this config so here we load this manually
   65     Core()->setConfig("dir.projects", Config()->getDirProjects());
   66 
   67     fillRecentFilesList();
   68     fillIOPluginsList();
   69     fillProjectsList();
   70 
   71     // Set last clicked tab
   72     ui->tabWidget->setCurrentIndex(Config()->getNewFileLastClicked());
   73 
   74     ui->loadProjectButton->setEnabled(ui->projectsListWidget->currentItem() != nullptr);
   75 
   76     /* Set focus on the TextInput */
   77     ui->newFileEdit->setFocus();
   78 }
   79 
   80 NewFileDialog::~NewFileDialog() {}
   81 
   82 void NewFileDialog::on_loadFileButton_clicked()
   83 {
   84     loadFile(ui->newFileEdit->text());
   85 }
   86 
   87 void NewFileDialog::on_selectFileButton_clicked()
   88 {
   89     QString currentDir = Config()->getRecentFolder();
   90     const QString &fileName = QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Select file"), currentDir));
   91 
   92     if (!fileName.isEmpty()) {
   93         ui->newFileEdit->setText(fileName);
   94         ui->loadFileButton->setFocus();
   95         Config()->setRecentFolder(QFileInfo(fileName).absolutePath());
   96     }
   97 }
   98 
   99 void NewFileDialog::on_selectProjectsDirButton_clicked()
  100 {
  101     auto currentDir = Config()->getDirProjects();
  102 
  103     if (currentDir.startsWith("~")) {
  104         currentDir = QDir::homePath() + currentDir.mid(1);
  105     }
  106     const QString &dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this,
  107         tr("Select project path (dir.projects)"),
  108         currentDir));
  109 
  110     if (dir.isEmpty()) {
  111         return;
  112     }
  113     if (!QFileInfo(dir).isWritable()) {
  114         QMessageBox::critical(this, tr("Permission denied"),
  115                               tr("You do not have write access to <b>%1</b>")
  116                               .arg(dir));
  117         return;
  118     }
  119 
  120     Config()->setDirProjects(dir);
  121     Core()->setConfig("dir.projects", dir);
  122     fillProjectsList();
  123 }
  124 
  125 void NewFileDialog::on_loadProjectButton_clicked()
  126 {
  127     QListWidgetItem *item = ui->projectsListWidget->currentItem();
  128 
  129     if (item == nullptr) {
  130         return;
  131     }
  132 
  133     loadProject(item->data(Qt::UserRole).toString());
  134 }
  135 
  136 void NewFileDialog::on_shellcodeButton_clicked()
  137 {
  138     QString shellcode = ui->shellcodeText->toPlainText();
  139     QString extractedCode = "";
  140     static const QRegularExpression rx("([0-9a-f]{2})", QRegularExpression::CaseInsensitiveOption);
  141     QRegularExpressionMatchIterator i = rx.globalMatch(shellcode);
  142     while (i.hasNext()) {
  143         QRegularExpressionMatch match = i.next();
  144         extractedCode.append(match.captured(1));
  145     }
  146     int size = extractedCode.size() / 2;
  147     if (size > 0) {
  148         loadShellcode(extractedCode, size);
  149     }
  150 }
  151 
  152 void NewFileDialog::on_recentsListWidget_itemClicked(QListWidgetItem *item)
  153 {
  154     QVariant data = item->data(Qt::UserRole);
  155     QString sitem = data.toString();
  156     ui->newFileEdit->setText(sitem);
  157 }
  158 
  159 void NewFileDialog::on_recentsListWidget_itemDoubleClicked(QListWidgetItem *item)
  160 {
  161     loadFile(item->data(Qt::UserRole).toString());
  162 }
  163 
  164 void NewFileDialog::on_projectsListWidget_itemSelectionChanged()
  165 {
  166     ui->loadProjectButton->setEnabled(ui->projectsListWidget->currentItem() != nullptr);
  167 }
  168 
  169 void NewFileDialog::on_projectsListWidget_itemDoubleClicked(QListWidgetItem *item)
  170 {
  171     loadProject(item->data(Qt::UserRole).toString());
  172 }
  173 
  174 void NewFileDialog::on_aboutButton_clicked()
  175 {
  176     AboutDialog *a = new AboutDialog(this);
  177     a->setAttribute(Qt::WA_DeleteOnClose);
  178     a->open();
  179 }
  180 
  181 void NewFileDialog::on_actionRemove_item_triggered()
  182 {
  183     // Remove selected item from recents list
  184     QListWidgetItem *item = ui->recentsListWidget->currentItem();
  185 
  186     if (item == nullptr)
  187         return;
  188 
  189     QVariant data = item->data(Qt::UserRole);
  190     QString sitem = data.toString();
  191 
  192     QSettings settings;
  193     QStringList files = settings.value("recentFileList").toStringList();
  194     files.removeAll(sitem);
  195     settings.setValue("recentFileList", files);
  196 
  197     ui->recentsListWidget->takeItem(ui->recentsListWidget->currentRow());
  198 
  199     ui->newFileEdit->clear();
  200 }
  201 
  202 void NewFileDialog::on_actionClear_all_triggered()
  203 {
  204     // Clear recent file list
  205     QSettings settings;
  206     QStringList files = settings.value("recentFileList").toStringList();
  207     files.clear();
  208 
  209     ui->recentsListWidget->clear();
  210     // TODO: if called from main window its ok, otherwise its not
  211     settings.setValue("recentFileList", files);
  212     ui->newFileEdit->clear();
  213 }
  214 
  215 void NewFileDialog::on_actionRemove_project_triggered()
  216 {
  217     CutterCore *core = Core();
  218 
  219     QListWidgetItem *item = ui->projectsListWidget->currentItem();
  220 
  221     if (item == nullptr)
  222         return;
  223 
  224     QVariant data = item->data(Qt::UserRole);
  225     QString sitem = data.toString();
  226 
  227     // Confirmation box
  228     QMessageBox msgBox(this);
  229     msgBox.setText(tr("Delete the project \"%1\" from disk ?").arg(sitem));
  230     msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
  231     int ret = msgBox.exec();
  232 
  233     switch (ret) {
  234     case QMessageBox::Yes:
  235         core->deleteProject(sitem);
  236         ui->projectsListWidget->takeItem(ui->projectsListWidget->currentRow());
  237         break;
  238     case QMessageBox::No:
  239     default:
  240         break;
  241     }
  242 }
  243 
  244 void NewFileDialog::dragEnterEvent(QDragEnterEvent *event)
  245 {
  246     // Accept drag & drop events only if they provide a URL
  247     if (event->mimeData()->hasUrls()) {
  248         event->acceptProposedAction();
  249     }
  250 }
  251 
  252 void NewFileDialog::dropEvent(QDropEvent *event)
  253 {
  254     // Accept drag & drop events only if they provide a URL
  255     if (event->mimeData()->urls().count() == 0) {
  256         qWarning() << "No URL in drop event, ignoring it.";
  257         return;
  258     }
  259 
  260     event->acceptProposedAction();
  261     loadFile(event->mimeData()->urls().first().toLocalFile());
  262 }
  263 
  264 bool NewFileDialog::fillRecentFilesList()
  265 {
  266     // Fill list with recent opened files
  267     QSettings settings;
  268 
  269     QStringList files = settings.value("recentFileList").toStringList();
  270 
  271     QMutableListIterator<QString> it(files);
  272     int i = 0;
  273     while (it.hasNext()) {
  274         const QString &file = QDir::toNativeSeparators(it.next());
  275         // Get stored files
  276 
  277         // Remove all but the file name
  278         const QString name = file.section(QDir::separator(), -1);
  279 
  280         // Get file info
  281         QFileInfo info(file);
  282         if (!info.exists()) {
  283             it.remove();
  284         } else {
  285             QListWidgetItem *item = new QListWidgetItem(
  286                 getIconFor(name, i++),
  287                 file + "\nCreated: " + info.created().toString() + "\nSize: " + qhelpers::formatBytecount(
  288                     info.size())
  289             );
  290             //":/img/icons/target.svg"), name );
  291             item->setData(Qt::UserRole, file);
  292             ui->recentsListWidget->addItem(item);
  293         }
  294     }
  295 
  296     // Removed files were deleted from the stringlist. Save it again.
  297     settings.setValue("recentFileList", files);
  298 
  299     return !files.isEmpty();
  300 }
  301 
  302 bool NewFileDialog::fillProjectsList()
  303 {
  304     CutterCore *core = Core();
  305 
  306     auto currentDir = Config()->getDirProjects();
  307 
  308     ui->projectsDirEdit->setText(currentDir);
  309 
  310     QStringList projects = core->getProjectNames();
  311     projects.sort(Qt::CaseInsensitive);
  312 
  313     ui->projectsListWidget->clear();
  314 
  315     int i = 0;
  316     for (const QString &project : projects) {
  317         QString info = QDir::toNativeSeparators(core->cmd("Pi " + project));
  318 
  319         QListWidgetItem *item = new QListWidgetItem(getIconFor(project, i++), project + "\n" + info);
  320 
  321         item->setData(Qt::UserRole, project);
  322         ui->projectsListWidget->addItem(item);
  323     }
  324 
  325     return !projects.isEmpty();
  326 }
  327 
  328 void NewFileDialog::fillIOPluginsList()
  329 {
  330     ui->ioPlugin->clear();
  331     ui->ioPlugin->addItem("file://");
  332     ui->ioPlugin->setItemData(0, tr("Open a file with no extra treatment."), Qt::ToolTipRole);
  333 
  334     int index = 1;
  335     QList<RIOPluginDescription> ioPlugins = Core()->getRIOPluginDescriptions();
  336     for (const RIOPluginDescription &plugin : ioPlugins) {
  337         // Hide debug plugins
  338         if (plugin.permissions.contains('d')) {
  339             continue;
  340         }
  341         for (const auto &uri : qAsConst(plugin.uris)) {
  342             if (uri == "file://") {
  343                 continue;
  344             }
  345             ui->ioPlugin->addItem(uri);
  346             ui->ioPlugin->setItemData(index, plugin.description, Qt::ToolTipRole);
  347             index++;
  348         }
  349     }
  350 }
  351 
  352 void NewFileDialog::loadFile(const QString &filename)
  353 {
  354     const QString &nativeFn = QDir::toNativeSeparators(filename);
  355     if (ui->ioPlugin->currentIndex() == 0 && !Core()->tryFile(nativeFn, false)
  356             && !ui->checkBox_FilelessOpen->isChecked()) {
  357         QMessageBox msgBox(this);
  358         msgBox.setText(tr("Select a new program or a previous one before continuing."));
  359         msgBox.exec();
  360         return;
  361     }
  362 
  363     // Add file to recent file list
  364     QSettings settings;
  365     QStringList files = settings.value("recentFileList").toStringList();
  366     files.removeAll(nativeFn);
  367     files.prepend(nativeFn);
  368     while (files.size() > MaxRecentFiles)
  369         files.removeLast();
  370 
  371     settings.setValue("recentFileList", files);
  372 
  373     // Close dialog and open MainWindow/InitialOptionsDialog
  374     QString ioFile = "";
  375     if (ui->ioPlugin->currentIndex()) {
  376         ioFile = ui->ioPlugin->currentText();
  377     }
  378     ioFile += nativeFn;
  379     InitialOptions options;
  380     options.filename = ioFile;
  381     main->openNewFile(options, ui->checkBox_FilelessOpen->isChecked());
  382 
  383     close();
  384 }
  385 
  386 void NewFileDialog::loadProject(const QString &project)
  387 {
  388     MainWindow *main = new MainWindow();
  389     main->openProject(project);
  390 
  391     close();
  392 }
  393 
  394 void NewFileDialog::loadShellcode(const QString &shellcode, const int size)
  395 {
  396     MainWindow *main = new MainWindow();
  397     InitialOptions options;
  398     options.filename = QString("malloc://%1").arg(size);
  399     options.shellcode = shellcode;
  400     main->openNewFile(options);
  401     close();
  402 }
  403 
  404 void NewFileDialog::on_tabWidget_currentChanged(int index)
  405 {
  406     Config()->setNewFileLastClicked(index);
  407 }