Exemple #1
0
 def __init__(self, parent, config_name=None, buttons=[], *args):
     """Creates dialog.
     'config_name' is used to get/set default window size from Config object
     'buttons' can be a list of names or (QPixmapWrapper,name[,tooltip]) tuples to provide
     custom buttons at the bottom of the dialog. When a button is clicked, the dialog
     emits SIGNAL("name").
     A "Close" button is always provided, this simply hides the dialog.
     """
     QDialog.__init__(self, parent, *args)
     self.setModal(False)
     lo = QVBoxLayout(self)
     # create viewer
     self.label = QLabel(self)
     self.label.setMargin(5)
     self.label.setWordWrap(True)
     lo.addWidget(self.label)
     self.label.hide()
     self.viewer = QTextBrowser(self)
     lo.addWidget(self.viewer)
     # self.viewer.setReadOnly(True)
     self.viewer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
     QObject.connect(self.viewer, SIGNAL("anchorClicked(const QUrl &)"), self._urlClicked)
     self._source = None
     lo.addSpacing(5)
     # create button bar
     btnfr = QFrame(self)
     btnfr.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
     # btnfr.setMargin(5)
     lo.addWidget(btnfr)
     lo.addSpacing(5)
     btnfr_lo = QHBoxLayout(btnfr)
     btnfr_lo.setMargin(5)
     # add user buttons
     self._user_buttons = {}
     for name in buttons:
         if isinstance(name, str):
             btn = QPushButton(name, btnfr)
         elif isinstance(name, (list, tuple)):
             if len(name) < 3:
                 pixmap, name = name
                 tip = None
             else:
                 pixmap, name, tip = name
             btn = QPushButton(pixmap.icon(), name, btnfr)
             if tip:
                 btn.setToolTip(tip)
         self._user_buttons[name] = btn
         btn._clicked = Kittens.utils.curry(self.emit, SIGNAL(name))
         self.connect(btn, SIGNAL("clicked()"), btn._clicked)
         btnfr_lo.addWidget(btn, 1)
     # add a Close button
     btnfr_lo.addStretch(100)
     closebtn = QPushButton(pixmaps.grey_round_cross.icon(), "Close", btnfr)
     self.connect(closebtn, SIGNAL("clicked()"), self.hide)
     btnfr_lo.addWidget(closebtn, 1)
     # resize selves
     self.config_name = config_name or "html-viewer"
     width = Config.getint('%s-width' % self.config_name, 512)
     height = Config.getint('%s-height' % self.config_name, 512)
     self.resize(QSize(width, height))
Exemple #2
0
 def __init__ (self,parent,*args):
   QDialog.__init__(self,parent,*args);
   self.setWindowTitle("Adding Log Entry");
   self.setWindowIcon(pixmaps.purr_logo.icon());
   self.setModal(False);
   ## create pop-up tip
   #self._has_tip = None;
   #self._dialog_tip = self.DialogTip(self);
   # create editor
   lo = QVBoxLayout(self);
   lo.setMargin(5);
   # lo.setResizeMode(QLayout.Minimum);
   self.editor = LogEntryEditor(self);
   self.dropDataProducts = self.editor.dropDataProducts;
   self.connect(self.editor,SIGNAL("filesSelected"),self,SIGNAL("filesSelected"));
   # connect draggedAwayFiles() signal so that files dragged away are removed from
   # the list
   self.connect(self.editor,SIGNAL("draggedAwayFiles"),self.editor.dropDataProducts);
   lo.addWidget(self.editor);
   lo.addSpacing(5);
   # create button bar
   btnfr = QFrame(self);
   btnfr.setSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.Fixed);
   # btnfr.setMargin(5);
   lo.addWidget(btnfr);
   lo.addSpacing(5);
   btnfr_lo = QHBoxLayout(btnfr);
   btnfr_lo.setMargin(0);
   newbtn = QPushButton(pixmaps.filesave.icon(),"Add new entry",btnfr);
   newbtn.setToolTip("""<P>Saves new log entry, along with any data products not marked
     as "ignore" or "banish".<P>""");
   self.ignorebtn = QPushButton(pixmaps.red_round_cross.icon(),"Ignore all",btnfr);
   self.ignorebtn.setEnabled(False);
   self.ignorebtn.setToolTip("""<P>Tells PURR to ignore all listed data products. PURR
     will not pounce on these files again until they have been modified.<P>""");
   cancelbtn = QPushButton(pixmaps.grey_round_cross.icon(),"Hide",btnfr);
   cancelbtn.setToolTip("""<P>Hides this dialog.<P>""");
   QObject.connect(newbtn,SIGNAL("clicked()"),self.addNewEntry);
   QObject.connect(self.ignorebtn,SIGNAL("clicked()"),self.ignoreAllDataProducts);
   QObject.connect(cancelbtn,SIGNAL("clicked()"),self.hide);
   for btn in (newbtn,self.ignorebtn,cancelbtn):
     btn.setAutoDefault(False);
   btnfr_lo.setMargin(0);
   btnfr_lo.addWidget(newbtn,2);
   btnfr_lo.addStretch(1);
   btnfr_lo.addWidget(self.ignorebtn,2);
   btnfr_lo.addStretch(1);
   btnfr_lo.addWidget(cancelbtn,2);
   self.setSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.MinimumExpanding);
   # resize selves
   self.setMinimumSize(256,512);
   width = Config.getint('entry-editor-width',512);
   height = Config.getint('entry-editor-height',512);
   self.resize(QSize(width,height));
Exemple #3
0
 def setWatchedFilePatterns(self, watch, ignore=[]):
     self._watch = watch
     self._ignore = ignore
     self._watch_patterns = set()
     for desc, patts in self._watch:
         self._watch_patterns.update(patts)
     dprint(1, "watching patterns", self._watch_patterns)
     self._ignore_patterns = set()
     for desc, patts in self._ignore:
         self._ignore_patterns.update(patts)
     dprint(1, "ignoring patterns", self._ignore_patterns)
     Config.set("watch-patterns", make_pattern_list(self._watch))
     Config.set("ignore-patterns", make_pattern_list(self._ignore))
Exemple #4
0
 def setWatchedFilePatterns(self, watch, ignore=[]):
     self._watch = watch
     self._ignore = ignore
     self._watch_patterns = set()
     for desc, patts in self._watch:
         self._watch_patterns.update(patts)
     dprint(1, "watching patterns", self._watch_patterns)
     self._ignore_patterns = set()
     for desc, patts in self._ignore:
         self._ignore_patterns.update(patts)
     dprint(1, "ignoring patterns", self._ignore_patterns)
     Config.set("watch-patterns", make_pattern_list(self._watch))
     Config.set("ignore-patterns", make_pattern_list(self._ignore))
Exemple #5
0
 def __init__(self, purrlog, watchdirs=None):
     QObject.__init__(self)
     # load and parse configuration
     # watched files
     watch = Config.get(
         "watch-patterns",
         "Images=*fits,*FITS,*jpg,*png;TDL configuration=.tdl.conf")
     self._watch = parse_pattern_list(watch)
     self._watch_patterns = set()
     for desc, patts in self._watch:
         self._watch_patterns.update(patts)
     dprint(1, "watching patterns", self._watch_patterns)
     # quietly watched files (dialog is not popped up)
     watch = Config.get("watch-patterns-quiet",
                        "TDL configuration=.tdl.conf")
     self._quiet = parse_pattern_list(watch)
     self._quiet_patterns = set()
     for desc, patts in self._quiet:
         self._quiet_patterns.update(patts)
     dprint(1, "quietly watching patterns", self._quiet_patterns)
     # ignored files
     ignore = Config.get(
         "ignore-patterns",
         "Hidden files=.*;Purr logs=*purrlog;MeqTree logs=meqtree.log;Python files=*.py*;Backup files=*~,*.bck;Measurement sets=*.MS,*.ms;CASA tables=table.f*,table.dat,table.info,table.lock"
     )
     self._ignore = parse_pattern_list(ignore)
     self._ignore_patterns = set()
     for desc, patts in self._ignore:
         self._ignore_patterns.update(patts)
     dprint(1, "ignoring patterns", self._ignore_patterns)
     # watched subdirectories
     subdirs = Config.get("watch-subdirs",
                          "MEP tables=*mep/funklets,table.dat")
     _re_patt = re.compile("^(.*)=(.*)/(.*)$")
     self._subdir_patterns = []
     for ss in subdirs.split(';'):
         match = _re_patt.match(ss)
         if match:
             desc = match.group(1)
             dir_patt = match.group(2).split(',')
             canary_patt = match.group(3).split(',')
             self._subdir_patterns.append((desc, dir_patt, canary_patt))
     dprint(1, "watching subdirectories", self._subdir_patterns)
     # attach to directories
     self.attached = False
     # will be True when we successfully attach
     self.other_lock = None
     # will be not None if another PURR holds a lock on this directory
     self.lockfile_fd = None
     self.lockfile_fobj = None
     self._attach(purrlog, watchdirs)
Exemple #6
0
 def __init__(self, purrlog, watchdirs=None):
     QObject.__init__(self)
     # load and parse configuration
     # watched files
     watch = Config.get("watch-patterns", "Images=*fits,*FITS,*jpg,*png;TDL configuration=.tdl.conf")
     self._watch = parse_pattern_list(watch)
     self._watch_patterns = set()
     for desc, patts in self._watch:
         self._watch_patterns.update(patts)
     dprint(1, "watching patterns", self._watch_patterns)
     # quietly watched files (dialog is not popped up)
     watch = Config.get("watch-patterns-quiet", "TDL configuration=.tdl.conf")
     self._quiet = parse_pattern_list(watch)
     self._quiet_patterns = set()
     for desc, patts in self._quiet:
         self._quiet_patterns.update(patts)
     dprint(1, "quietly watching patterns", self._quiet_patterns)
     # ignored files
     ignore = Config.get("ignore-patterns",
                         "Hidden files=.*;Purr logs=*purrlog;MeqTree logs=meqtree.log;Python files=*.py*;Backup files=*~,*.bck;Measurement sets=*.MS,*.ms;CASA tables=table.f*,table.dat,table.info,table.lock")
     self._ignore = parse_pattern_list(ignore)
     self._ignore_patterns = set()
     for desc, patts in self._ignore:
         self._ignore_patterns.update(patts)
     dprint(1, "ignoring patterns", self._ignore_patterns)
     # watched subdirectories
     subdirs = Config.get("watch-subdirs", "MEP tables=*mep/funklets,table.dat")
     _re_patt = re.compile("^(.*)=(.*)/(.*)$")
     self._subdir_patterns = []
     for ss in subdirs.split(';'):
         match = _re_patt.match(ss)
         if match:
             desc = match.group(1)
             dir_patt = match.group(2).split(',')
             canary_patt = match.group(3).split(',')
             self._subdir_patterns.append((desc, dir_patt, canary_patt))
     dprint(1, "watching subdirectories", self._subdir_patterns)
     # attach to directories
     self.attached = False;  # will be True when we successfully attach
     self.other_lock = None;  # will be not None if another PURR holds a lock on this directory
     self.lockfile_fd = None
     self.lockfile_fobj = None
     self._attach(purrlog, watchdirs)
Exemple #7
0
    def __init__ (self,parent,directories=False):
      QFileDialog.__init__(self);
      self.setWindowTitle("PURR: Add Data Products");
      self.dirlist = None;
      # add filters
      #self._dirfilter = "Any directories (*)";
      #if hasattr(self,'setNameFilters'):  # qt4.4+
      #  self.setNameFilters(["Any files (*)",self._dirfilter]);
      #else:
      #  self.setFilters(["Any files (*)",self._dirfilter]);
      # connect signals (translates into a SIGNAL with string arguments)
      self.connect(self,SIGNAL("filesSelected(const QStringList&)"),self._filesSelected);
#      self.connect(self,SIGNAL("fileSelected(const QString&)"),self._fileSelected);
      self.connect(self,SIGNAL("currentChanged(const QString&)"),self._fileHighlighted);
      # self.connect(self,SIGNAL("filterSelected(const QString&)"),self._filterSelected);
      # resize selves
      self.config_name = "add-file-dialog";
      width = Config.getint('%s-width'%self.config_name,768);
      height = Config.getint('%s-height'%self.config_name,512);
      self.resize(QSize(width,height));
Exemple #8
0
 def resizeEvent (self,ev):
   QDialog.resizeEvent(self,ev);
   sz = ev.size();
   Config.set('entry-editor-width',sz.width());
   Config.set('entry-editor-height',sz.height());
Exemple #9
0
 def resizeEvent (self,ev):
   QFileDialog.resizeEvent(self,ev);
   sz = ev.size();
   Config.set('%s-width'%self.config_name,sz.width());
   Config.set('%s-height'%self.config_name,sz.height());
Exemple #10
0
  def __init__ (self,parent,*args):
    QDialog.__init__(self,parent,*args);
    self.setModal(False);
    # make stack for viewer and editor components
    lo = QVBoxLayout(self);
    lo.setMargin(5);
    self.wstack = QStackedWidget(self);
    lo.addWidget(self.wstack);
    self.wstack.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding);
    # make editor panel
    self.editor_panel = QWidget(self.wstack);
    self.editor_panel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding);
    self.wstack.addWidget(self.editor_panel);
    lo = QVBoxLayout(self.editor_panel);
    lo.setMargin(0);
    # create editor
    self.editor = LogEntryEditor(self.editor_panel);
    self.connect(self.editor,SIGNAL("updated"),self._entryUpdated);
    self.connect(self.editor,SIGNAL("filesSelected"),self,SIGNAL("filesSelected"));
    self.connect(self.editor,SIGNAL("creatingDataProduct"),
                 self,SIGNAL("creatingDataProduct"));
    lo.addWidget(self.editor);
    self.dropDataProducts = self.editor.dropDataProducts;
    # create button bar for editor
    btnfr = QFrame(self.editor_panel);
    btnfr.setSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.Fixed);
    # btnfr.setMargin(5);
    lo.addWidget(btnfr);
    lo.addSpacing(5);
    btnfr_lo = QHBoxLayout(btnfr);
    self.wsave = QPushButton(pixmaps.filesave.icon(),"Save",btnfr);
    QObject.connect(self.wsave,SIGNAL("clicked()"),self._saveEntry);
    cancelbtn = QPushButton(pixmaps.grey_round_cross.icon(),"Cancel",btnfr);
    QObject.connect(cancelbtn,SIGNAL("clicked()"),self._cancelEntry);
    for btn in (self.wsave,cancelbtn):
      btn.setAutoDefault(False);
    btnfr_lo.setMargin(0);
    btnfr_lo.addWidget(self.wsave,1);
    btnfr_lo.addStretch(1);
    btnfr_lo.addWidget(cancelbtn,1);

    # create viewer panel
    self.viewer_panel = QWidget(self.wstack);
    self.viewer_panel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding);
    self.wstack.addWidget(self.viewer_panel);
    lo = QVBoxLayout(self.viewer_panel);
    lo.setMargin(0);
    label = QLabel("""<P>Below is an HTML rendering of your log entry. Note that this is
      only a bare-bones viewer, so only some links will work. In particular,
      you may click on a link associated with a saved data product to get a menu of related actions. To edit this entry, click the Edit button below.
      </P>""",self.viewer_panel);
    label.setWordWrap(True);
    label.setMargin(5);
    lo.addWidget(label);
    self.viewer = self.EntryTextBrowser(self.viewer_panel);
    self.viewer.setOpenLinks(False);
    self.viewer.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding);
    self._viewer_source = None;
    QObject.connect(self.viewer,SIGNAL("anchorClicked(const QUrl &)"),self._urlClicked);
    lo.addWidget(self.viewer);
    lo.addSpacing(5);
    # create button bar
    btnfr = QFrame(self.viewer_panel);
    btnfr.setSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.Fixed);
    # btnfr.setMargin(5);
    lo.addWidget(btnfr);
    lo.addSpacing(5);
    btnfr_lo = QHBoxLayout(btnfr);
    btnfr_lo.setMargin(0);
    btn = self.wprev = QPushButton(pixmaps.previous.icon(),"Previous",btnfr);
    QObject.connect(btn,SIGNAL("clicked()"),self,SIGNAL("previous()"));
    btnfr_lo.addWidget(btn,1);
    btnfr_lo.addSpacing(5);
    btn = self.wnext = QPushButton(pixmaps.next.icon(),"Next",btnfr);
    QObject.connect(btn,SIGNAL("clicked()"),self,SIGNAL("next()"));
    btnfr_lo.addWidget(btn,1);
    btnfr_lo.addSpacing(5);
    btn = self.wedit = QPushButton(pixmaps.edit.icon(),"Edit",btnfr);
    QObject.connect(btn,SIGNAL("clicked()"),self._editEntry);
    btnfr_lo.addWidget(btn,1);
    btnfr_lo.addStretch(1)
    btn = self.wclose = QPushButton(pixmaps.grey_round_cross.icon(),"Close",btnfr);
    QObject.connect(btn,SIGNAL("clicked()"),self.hide);
    btnfr_lo.addWidget(btn,1);
    # create popup menu for data products
    self._dp_menu = menu = QMenu(self);
    self._dp_menu_title = QLabel();
    self._dp_menu_title.setMargin(5);
    self._dp_menu_title_wa = wa=QWidgetAction(self);
    wa.setDefaultWidget(self._dp_menu_title);
    menu.addAction(wa);
    menu.addSeparator();
    menu.addAction(pixmaps.editcopy.icon(),"Restore file(s) from archived copy",self._restoreDPFromArchive);
    menu.addAction(pixmaps.editpaste.icon(),"Copy pathname of archived copy to clipboard",self._copyDPToClipboard);
    menu.addAction("Drag-and-drop archived copy",self._startDPDrag);
    self._dp_menu_on = None;

    # resize selves
    width = Config.getint('entry-viewer-width',512);
    height = Config.getint('entry-viewer-height',512);
    self.resize(QSize(width,height));
    # other init
    self.entry = None;
    self.updated = False;
Exemple #11
0
 def resizeEvent(self, ev):
     QMainWindow.resizeEvent(self, ev)
     sz = ev.size()
     Config.set('main-window-width', sz.width())
     Config.set('main-window-height', sz.height())
Exemple #12
0
    def __init__(self, parent, hide_on_close=False):
        QMainWindow.__init__(self, parent)
        self._hide_on_close = hide_on_close
        # replace the BusyIndicator class with a GUI-aware one
        Purr.BusyIndicator = BusyIndicator
        self._pounce = False
        # we keep a small stack of previously active purrers. This makes directory changes
        # faster (when going back and forth between dirs)
        # current purrer
        self.purrer = None
        self.purrer_stack = []
        # Purr pipes for receiving remote commands
        self.purrpipes = {}
        # init GUI
        self.setWindowTitle("PURR")
        self.setWindowIcon(pixmaps.purr_logo.icon())
        cw = QWidget(self)
        self.setCentralWidget(cw)
        cwlo = QVBoxLayout(cw)
        cwlo.setContentsMargins(0, 0, 0, 0)
        cwlo.setMargin(5)
        cwlo.setSpacing(0)
        toplo = QHBoxLayout();
        cwlo.addLayout(toplo)

        # About dialog
        self._about_dialog = QMessageBox(self)
        self._about_dialog.setWindowTitle("About PURR")
        self._about_dialog.setText(self.about_message + """
        <P>PURR is not watching any directories right now. You may need to restart it, and give it
  some directory names on the command line.</P>""")
        self._about_dialog.setIconPixmap(pixmaps.purr_logo.pm())
        # Log viewer dialog
        self.viewer_dialog = HTMLViewerDialog(self, config_name="log-viewer",
                                              buttons=[(pixmaps.blue_round_reload, "Regenerate",
                                                        """<P>Regenerates your log's HTML code from scratch. This can be useful if
                                                        your PURR version has changed, or if there was an error of some kind
                                                        the last time the files were generated.</P>
                                                        """)])
        self._viewer_timestamp = None
        self.connect(self.viewer_dialog, SIGNAL("Regenerate"), self._regenerateLog)
        self.connect(self.viewer_dialog, SIGNAL("viewPath"), self._viewPath)

        # Log title toolbar
        title_tb = QToolBar(cw)
        title_tb.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        title_tb.setIconSize(QSize(16, 16))
        cwlo.addWidget(title_tb)
        title_label = QLabel("Purrlog title:", title_tb)
        title_tb.addWidget(title_label)
        self.title_editor = QLineEdit(title_tb)
        title_tb.addWidget(self.title_editor)
        self.connect(self.title_editor, SIGNAL("editingFinished()"), self._titleChanged)
        tip = """<P>This is your current log title. To rename the log, enter new name here and press Enter.</P>"""
        title_label.setToolTip(tip)
        self.title_editor.setToolTip(tip)
        self.wviewlog = title_tb.addAction(pixmaps.openbook.icon(), "View", self._showViewerDialog)
        self.wviewlog.setToolTip("Click to see an HTML rendering of your current log.")
        qa = title_tb.addAction(pixmaps.purr_logo.icon(), "About...", self._about_dialog.exec_)
        qa.setToolTip("<P>Click to see the About... dialog, which will tell you something about PURR.</P>")

        self.wdirframe = QFrame(cw)
        cwlo.addWidget(self.wdirframe)
        self.dirs_lo = QVBoxLayout(self.wdirframe)
        self.dirs_lo.setMargin(5)
        self.dirs_lo.setContentsMargins(5, 0, 5, 5)
        self.dirs_lo.setSpacing(0)
        self.wdirframe.setFrameStyle(QFrame.Box | QFrame.Raised)
        self.wdirframe.setLineWidth(1)

        ## Directories toolbar
        dirs_tb = QToolBar(self.wdirframe)
        dirs_tb.setToolButtonStyle(Qt.ToolButtonIconOnly)
        dirs_tb.setIconSize(QSize(16, 16))
        self.dirs_lo.addWidget(dirs_tb)
        label = QLabel("Monitoring directories:", dirs_tb)
        self._dirs_tip = """<P>PURR can monitor your working directories for new or updated files. If there's a checkmark
      next to the directory name in this list, PURR is monitoring it.</P>

      <P>If the checkmark is grey, PURR is monitoring things unobtrusively. When a new or updated file is detected in he monitored directory,
      it is quietly added to the list of files in the "New entry" window, even if this window is not currently visible.</P>

      <P>If the checkmark is black, PURR will be more obtrusive. Whenever a new or updated file is detected, the "New entry" window will
      pop up automatically. This is called "pouncing", and some people find it annoying.</P>
      """
        label.setToolTip(self._dirs_tip)
        label.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        dirs_tb.addWidget(label)

        # add directory list widget
        self.wdirlist = DirectoryListWidget(self.wdirframe)
        self.wdirlist.setToolTip(self._dirs_tip)
        QObject.connect(self.wdirlist, SIGNAL("directoryStateChanged"), self._changeWatchedDirState)
        self.dirs_lo.addWidget(self.wdirlist)
        # self.wdirlist.setMaximumSize(1000000,64)

        # add directory button
        add = dirs_tb.addAction(pixmaps.list_add.icon(), "Add", self._showAddDirectoryDialog)
        add.setToolTip("<P>Click to add another directory to be monitored.</P>")

        # remove directory button
        delbtn = dirs_tb.addAction(pixmaps.list_remove.icon(), "Remove", self.wdirlist.removeCurrent)
        delbtn.setEnabled(False)
        delbtn.setToolTip("<P>Click to removed the currently selected directory from the list.</P>")
        QObject.connect(self.wdirlist, SIGNAL("hasSelection"), delbtn.setEnabled)

        #    # qa = dirs_tb.addAction(pixmaps.blue_round_reload.icon(),"Rescan",self._forceRescan)
        #    # qa.setToolTip("Click to rescan the directories for any new or updated files.")
        #    self.wshownew = QCheckBox("show new files",dirs_tb)
        #    dirs_tb.addWidget(self.wshownew)
        #    self.wshownew.setCheckState(Qt.Checked)
        #    self.wshownew.setToolTip("""<P>If this is checked, the "New entry" window will pop up automatically whenever
        #  new or updated files are detected. If this is unchecked, the files will be added to the window quietly
        #        and unobtrusively; you can show the window manually by clicking on the "New entry..." button below.</P>""")
        #    self._dir_entries = {}

        cwlo.addSpacing(5)

        wlogframe = QFrame(cw)
        cwlo.addWidget(wlogframe)
        log_lo = QVBoxLayout(wlogframe)
        log_lo.setMargin(5)
        log_lo.setContentsMargins(5, 5, 5, 5)
        log_lo.setSpacing(0)
        wlogframe.setFrameStyle(QFrame.Box | QFrame.Raised)
        wlogframe.setLineWidth(1)

        # listview of log entries
        self.etw = LogEntryTree(cw)
        log_lo.addWidget(self.etw, 1)
        self.etw.header().setDefaultSectionSize(128)
        self.etw.header().setMovable(False)
        self.etw.setHeaderLabels(["date", "entry title", "comment"])
        if hasattr(QHeaderView, 'ResizeToContents'):
            self.etw.header().setResizeMode(0, QHeaderView.ResizeToContents)
        else:
            self.etw.header().setResizeMode(0, QHeaderView.Custom)
            self.etw.header().resizeSection(0, 120)
        self.etw.header().setResizeMode(1, QHeaderView.Interactive)
        self.etw.header().setResizeMode(2, QHeaderView.Stretch)
        self.etw.header().show()
        try:
            self.etw.setAllColumnsShowFocus(True)
        except AttributeError:
            pass;  # Qt 4.2+
        # self.etw.setShowToolTips(True)
        self.etw.setSortingEnabled(False)
        # self.etw.setColumnAlignment(2,Qt.AlignLeft|Qt.AlignTop)
        self.etw.setSelectionMode(QTreeWidget.ExtendedSelection)
        self.etw.setRootIsDecorated(True)
        self.connect(self.etw, SIGNAL("itemSelectionChanged()"), self._entrySelectionChanged)
        self.connect(self.etw, SIGNAL("itemActivated(QTreeWidgetItem*,int)"), self._viewEntryItem)
        self.connect(self.etw, SIGNAL("itemContextMenuRequested"), self._showItemContextMenu)
        # create popup menu for data products
        self._archived_dp_menu = menu = QMenu(self)
        self._archived_dp_menu_title = QLabel()
        self._archived_dp_menu_title.setMargin(5)
        self._archived_dp_menu_title_wa = wa = QWidgetAction(self)
        wa.setDefaultWidget(self._archived_dp_menu_title)
        menu.addAction(wa)
        menu.addSeparator()
        menu.addAction(pixmaps.editcopy.icon(), "Restore file(s) from archived copy", self._restoreItemFromArchive)
        menu.addAction(pixmaps.editpaste.icon(), "Copy pathname of archived copy to clipboard",
                       self._copyItemToClipboard)
        self._current_item = None
        # create popup menu for entries
        self._entry_menu = menu = QMenu(self)
        self._entry_menu_title = QLabel()
        self._entry_menu_title.setMargin(5)
        self._entry_menu_title_wa = wa = QWidgetAction(self)
        wa.setDefaultWidget(self._entry_menu_title)
        menu.addAction(wa)
        menu.addSeparator()
        menu.addAction(pixmaps.filefind.icon(), "View this log entry", self._viewEntryItem)
        menu.addAction(pixmaps.editdelete.icon(), "Delete this log entry", self._deleteSelectedEntries)
        # buttons at bottom
        log_lo.addSpacing(5)
        btnlo = QHBoxLayout()
        log_lo.addLayout(btnlo)
        self.wnewbtn = QPushButton(pixmaps.filenew.icon(), "New entry...", cw)
        self.wnewbtn.setToolTip("Click to add a new log entry.")
        # self.wnewbtn.setFlat(True)
        self.wnewbtn.setEnabled(False)
        btnlo.addWidget(self.wnewbtn)
        btnlo.addSpacing(5)
        self.weditbtn = QPushButton(pixmaps.filefind.icon(), "View entry...", cw)
        self.weditbtn.setToolTip("Click to view or edit the selected log entry/")
        # self.weditbtn.setFlat(True)
        self.weditbtn.setEnabled(False)
        self.connect(self.weditbtn, SIGNAL("clicked()"), self._viewEntryItem)
        btnlo.addWidget(self.weditbtn)
        btnlo.addSpacing(5)
        self.wdelbtn = QPushButton(pixmaps.editdelete.icon(), "Delete", cw)
        self.wdelbtn.setToolTip("Click to delete the selected log entry or entries.")
        # self.wdelbtn.setFlat(True)
        self.wdelbtn.setEnabled(False)
        self.connect(self.wdelbtn, SIGNAL("clicked()"), self._deleteSelectedEntries)
        btnlo.addWidget(self.wdelbtn)
        # enable status line
        self.statusBar().show()
        Purr.progressMessage = self.message
        self._prev_msg = None
        # editor dialog for new entry
        self.new_entry_dialog = Purr.Editors.NewLogEntryDialog(self)
        self.connect(self.new_entry_dialog, SIGNAL("newLogEntry"), self._newLogEntry)
        self.connect(self.new_entry_dialog, SIGNAL("filesSelected"), self._addDPFiles)
        self.connect(self.wnewbtn, SIGNAL("clicked()"), self.new_entry_dialog.show)
        self.connect(self.new_entry_dialog, SIGNAL("shown"), self._checkPounceStatus)
        # entry viewer dialog
        self.view_entry_dialog = Purr.Editors.ExistingLogEntryDialog(self)
        self.connect(self.view_entry_dialog, SIGNAL("previous()"), self._viewPrevEntry)
        self.connect(self.view_entry_dialog, SIGNAL("next()"), self._viewNextEntry)
        self.connect(self.view_entry_dialog, SIGNAL("viewPath"), self._viewPath)
        self.connect(self.view_entry_dialog, SIGNAL("filesSelected"), self._addDPFilesToOldEntry)
        self.connect(self.view_entry_dialog, SIGNAL("entryChanged"), self._entryChanged)
        # saving a data product to an older entry will automatically drop it from the
        # new entry dialog
        self.connect(self.view_entry_dialog, SIGNAL("creatingDataProduct"),
                     self.new_entry_dialog.dropDataProducts)
        # resize selves
        width = Config.getint('main-window-width', 512)
        height = Config.getint('main-window-height', 512)
        self.resize(QSize(width, height))
        # create timer for pouncing
        self._timer = QTimer(self)
        self.connect(self._timer, SIGNAL("timeout()"), self._rescan)
        # create dict mapping index.html paths to entry numbers
        self._index_paths = {}
Exemple #13
0
 def resizeEvent(self, ev):
     QDialog.resizeEvent(self, ev)
     sz = ev.size()
     Config.set('%s-width' % self.config_name, sz.width())
     Config.set('%s-height' % self.config_name, sz.height())
Exemple #14
0
 def resizeEvent(self, ev):
     QMainWindow.resizeEvent(self, ev)
     sz = ev.size()
     Config.set('main-window-width', sz.width())
     Config.set('main-window-height', sz.height())
Exemple #15
0
 def __init__(self, parent, config_name=None, buttons=[], *args):
     """Creates dialog.
     'config_name' is used to get/set default window size from Config object
     'buttons' can be a list of names or (QPixmapWrapper,name[,tooltip]) tuples to provide
     custom buttons at the bottom of the dialog. When a button is clicked, the dialog
     emits SIGNAL("name").
     A "Close" button is always provided, this simply hides the dialog.
     """
     QDialog.__init__(self, parent, *args)
     self.setModal(False)
     lo = QVBoxLayout(self)
     # create viewer
     self.label = QLabel(self)
     self.label.setMargin(5)
     self.label.setWordWrap(True)
     lo.addWidget(self.label)
     self.label.hide()
     self.viewer = QTextBrowser(self)
     lo.addWidget(self.viewer)
     # self.viewer.setReadOnly(True)
     self.viewer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
     QObject.connect(self.viewer, SIGNAL("anchorClicked(const QUrl &)"),
                     self._urlClicked)
     self._source = None
     lo.addSpacing(5)
     # create button bar
     btnfr = QFrame(self)
     btnfr.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
     # btnfr.setMargin(5)
     lo.addWidget(btnfr)
     lo.addSpacing(5)
     btnfr_lo = QHBoxLayout(btnfr)
     btnfr_lo.setMargin(5)
     # add user buttons
     self._user_buttons = {}
     for name in buttons:
         if isinstance(name, str):
             btn = QPushButton(name, btnfr)
         elif isinstance(name, (list, tuple)):
             if len(name) < 3:
                 pixmap, name = name
                 tip = None
             else:
                 pixmap, name, tip = name
             btn = QPushButton(pixmap.icon(), name, btnfr)
             if tip:
                 btn.setToolTip(tip)
         self._user_buttons[name] = btn
         btn._clicked = Kittens.utils.curry(self.emit, SIGNAL(name))
         self.connect(btn, SIGNAL("clicked()"), btn._clicked)
         btnfr_lo.addWidget(btn, 1)
     # add a Close button
     btnfr_lo.addStretch(100)
     closebtn = QPushButton(pixmaps.grey_round_cross.icon(), "Close", btnfr)
     self.connect(closebtn, SIGNAL("clicked()"), self.hide)
     btnfr_lo.addWidget(closebtn, 1)
     # resize selves
     self.config_name = config_name or "html-viewer"
     width = Config.getint('%s-width' % self.config_name, 512)
     height = Config.getint('%s-height' % self.config_name, 512)
     self.resize(QSize(width, height))
Exemple #16
0
    def __init__(self, parent, hide_on_close=False):
        QMainWindow.__init__(self, parent)
        self._hide_on_close = hide_on_close
        # replace the BusyIndicator class with a GUI-aware one
        Purr.BusyIndicator = BusyIndicator
        self._pounce = False
        # we keep a small stack of previously active purrers. This makes directory changes
        # faster (when going back and forth between dirs)
        # current purrer
        self.purrer = None
        self.purrer_stack = []
        # Purr pipes for receiving remote commands
        self.purrpipes = {}
        # init GUI
        self.setWindowTitle("PURR")
        self.setWindowIcon(pixmaps.purr_logo.icon())
        cw = QWidget(self)
        self.setCentralWidget(cw)
        cwlo = QVBoxLayout(cw)
        cwlo.setContentsMargins(0, 0, 0, 0)
        cwlo.setMargin(5)
        cwlo.setSpacing(0)
        toplo = QHBoxLayout()
        cwlo.addLayout(toplo)

        # About dialog
        self._about_dialog = QMessageBox(self)
        self._about_dialog.setWindowTitle("About PURR")
        self._about_dialog.setText(self.about_message + """
        <P>PURR is not watching any directories right now. You may need to restart it, and give it
  some directory names on the command line.</P>""")
        self._about_dialog.setIconPixmap(pixmaps.purr_logo.pm())
        # Log viewer dialog
        self.viewer_dialog = HTMLViewerDialog(
            self,
            config_name="log-viewer",
            buttons=
            [(pixmaps.blue_round_reload, "Regenerate",
              """<P>Regenerates your log's HTML code from scratch. This can be useful if
                                                        your PURR version has changed, or if there was an error of some kind
                                                        the last time the files were generated.</P>
                                                        """)])
        self._viewer_timestamp = None
        self.connect(self.viewer_dialog, SIGNAL("Regenerate"),
                     self._regenerateLog)
        self.connect(self.viewer_dialog, SIGNAL("viewPath"), self._viewPath)

        # Log title toolbar
        title_tb = QToolBar(cw)
        title_tb.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        title_tb.setIconSize(QSize(16, 16))
        cwlo.addWidget(title_tb)
        title_label = QLabel("Purrlog title:", title_tb)
        title_tb.addWidget(title_label)
        self.title_editor = QLineEdit(title_tb)
        title_tb.addWidget(self.title_editor)
        self.connect(self.title_editor, SIGNAL("editingFinished()"),
                     self._titleChanged)
        tip = """<P>This is your current log title. To rename the log, enter new name here and press Enter.</P>"""
        title_label.setToolTip(tip)
        self.title_editor.setToolTip(tip)
        self.wviewlog = title_tb.addAction(pixmaps.openbook.icon(), "View",
                                           self._showViewerDialog)
        self.wviewlog.setToolTip(
            "Click to see an HTML rendering of your current log.")
        qa = title_tb.addAction(pixmaps.purr_logo.icon(), "About...",
                                self._about_dialog.exec_)
        qa.setToolTip(
            "<P>Click to see the About... dialog, which will tell you something about PURR.</P>"
        )

        self.wdirframe = QFrame(cw)
        cwlo.addWidget(self.wdirframe)
        self.dirs_lo = QVBoxLayout(self.wdirframe)
        self.dirs_lo.setMargin(5)
        self.dirs_lo.setContentsMargins(5, 0, 5, 5)
        self.dirs_lo.setSpacing(0)
        self.wdirframe.setFrameStyle(QFrame.Box | QFrame.Raised)
        self.wdirframe.setLineWidth(1)

        ## Directories toolbar
        dirs_tb = QToolBar(self.wdirframe)
        dirs_tb.setToolButtonStyle(Qt.ToolButtonIconOnly)
        dirs_tb.setIconSize(QSize(16, 16))
        self.dirs_lo.addWidget(dirs_tb)
        label = QLabel("Monitoring directories:", dirs_tb)
        self._dirs_tip = """<P>PURR can monitor your working directories for new or updated files. If there's a checkmark
      next to the directory name in this list, PURR is monitoring it.</P>

      <P>If the checkmark is grey, PURR is monitoring things unobtrusively. When a new or updated file is detected in he monitored directory,
      it is quietly added to the list of files in the "New entry" window, even if this window is not currently visible.</P>

      <P>If the checkmark is black, PURR will be more obtrusive. Whenever a new or updated file is detected, the "New entry" window will
      pop up automatically. This is called "pouncing", and some people find it annoying.</P>
      """
        label.setToolTip(self._dirs_tip)
        label.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        dirs_tb.addWidget(label)

        # add directory list widget
        self.wdirlist = DirectoryListWidget(self.wdirframe)
        self.wdirlist.setToolTip(self._dirs_tip)
        QObject.connect(self.wdirlist, SIGNAL("directoryStateChanged"),
                        self._changeWatchedDirState)
        self.dirs_lo.addWidget(self.wdirlist)
        # self.wdirlist.setMaximumSize(1000000,64)

        # add directory button
        add = dirs_tb.addAction(pixmaps.list_add.icon(), "Add",
                                self._showAddDirectoryDialog)
        add.setToolTip(
            "<P>Click to add another directory to be monitored.</P>")

        # remove directory button
        delbtn = dirs_tb.addAction(pixmaps.list_remove.icon(), "Remove",
                                   self.wdirlist.removeCurrent)
        delbtn.setEnabled(False)
        delbtn.setToolTip(
            "<P>Click to removed the currently selected directory from the list.</P>"
        )
        QObject.connect(self.wdirlist, SIGNAL("hasSelection"),
                        delbtn.setEnabled)

        #    # qa = dirs_tb.addAction(pixmaps.blue_round_reload.icon(),"Rescan",self._forceRescan)
        #    # qa.setToolTip("Click to rescan the directories for any new or updated files.")
        #    self.wshownew = QCheckBox("show new files",dirs_tb)
        #    dirs_tb.addWidget(self.wshownew)
        #    self.wshownew.setCheckState(Qt.Checked)
        #    self.wshownew.setToolTip("""<P>If this is checked, the "New entry" window will pop up automatically whenever
        #  new or updated files are detected. If this is unchecked, the files will be added to the window quietly
        #        and unobtrusively; you can show the window manually by clicking on the "New entry..." button below.</P>""")
        #    self._dir_entries = {}

        cwlo.addSpacing(5)

        wlogframe = QFrame(cw)
        cwlo.addWidget(wlogframe)
        log_lo = QVBoxLayout(wlogframe)
        log_lo.setMargin(5)
        log_lo.setContentsMargins(5, 5, 5, 5)
        log_lo.setSpacing(0)
        wlogframe.setFrameStyle(QFrame.Box | QFrame.Raised)
        wlogframe.setLineWidth(1)

        # listview of log entries
        self.etw = LogEntryTree(cw)
        log_lo.addWidget(self.etw, 1)
        self.etw.header().setDefaultSectionSize(128)
        self.etw.header().setMovable(False)
        self.etw.setHeaderLabels(["date", "entry title", "comment"])
        if hasattr(QHeaderView, 'ResizeToContents'):
            self.etw.header().setResizeMode(0, QHeaderView.ResizeToContents)
        else:
            self.etw.header().setResizeMode(0, QHeaderView.Custom)
            self.etw.header().resizeSection(0, 120)
        self.etw.header().setResizeMode(1, QHeaderView.Interactive)
        self.etw.header().setResizeMode(2, QHeaderView.Stretch)
        self.etw.header().show()
        try:
            self.etw.setAllColumnsShowFocus(True)
        except AttributeError:
            pass
            # Qt 4.2+
        # self.etw.setShowToolTips(True)
        self.etw.setSortingEnabled(False)
        # self.etw.setColumnAlignment(2,Qt.AlignLeft|Qt.AlignTop)
        self.etw.setSelectionMode(QTreeWidget.ExtendedSelection)
        self.etw.setRootIsDecorated(True)
        self.connect(self.etw, SIGNAL("itemSelectionChanged()"),
                     self._entrySelectionChanged)
        self.connect(self.etw, SIGNAL("itemActivated(QTreeWidgetItem*,int)"),
                     self._viewEntryItem)
        self.connect(self.etw, SIGNAL("itemContextMenuRequested"),
                     self._showItemContextMenu)
        # create popup menu for data products
        self._archived_dp_menu = menu = QMenu(self)
        self._archived_dp_menu_title = QLabel()
        self._archived_dp_menu_title.setMargin(5)
        self._archived_dp_menu_title_wa = wa = QWidgetAction(self)
        wa.setDefaultWidget(self._archived_dp_menu_title)
        menu.addAction(wa)
        menu.addSeparator()
        menu.addAction(pixmaps.editcopy.icon(),
                       "Restore file(s) from archived copy",
                       self._restoreItemFromArchive)
        menu.addAction(pixmaps.editpaste.icon(),
                       "Copy pathname of archived copy to clipboard",
                       self._copyItemToClipboard)
        self._current_item = None
        # create popup menu for entries
        self._entry_menu = menu = QMenu(self)
        self._entry_menu_title = QLabel()
        self._entry_menu_title.setMargin(5)
        self._entry_menu_title_wa = wa = QWidgetAction(self)
        wa.setDefaultWidget(self._entry_menu_title)
        menu.addAction(wa)
        menu.addSeparator()
        menu.addAction(pixmaps.filefind.icon(), "View this log entry",
                       self._viewEntryItem)
        menu.addAction(pixmaps.editdelete.icon(), "Delete this log entry",
                       self._deleteSelectedEntries)
        # buttons at bottom
        log_lo.addSpacing(5)
        btnlo = QHBoxLayout()
        log_lo.addLayout(btnlo)
        self.wnewbtn = QPushButton(pixmaps.filenew.icon(), "New entry...", cw)
        self.wnewbtn.setToolTip("Click to add a new log entry.")
        # self.wnewbtn.setFlat(True)
        self.wnewbtn.setEnabled(False)
        btnlo.addWidget(self.wnewbtn)
        btnlo.addSpacing(5)
        self.weditbtn = QPushButton(pixmaps.filefind.icon(), "View entry...",
                                    cw)
        self.weditbtn.setToolTip(
            "Click to view or edit the selected log entry/")
        # self.weditbtn.setFlat(True)
        self.weditbtn.setEnabled(False)
        self.connect(self.weditbtn, SIGNAL("clicked()"), self._viewEntryItem)
        btnlo.addWidget(self.weditbtn)
        btnlo.addSpacing(5)
        self.wdelbtn = QPushButton(pixmaps.editdelete.icon(), "Delete", cw)
        self.wdelbtn.setToolTip(
            "Click to delete the selected log entry or entries.")
        # self.wdelbtn.setFlat(True)
        self.wdelbtn.setEnabled(False)
        self.connect(self.wdelbtn, SIGNAL("clicked()"),
                     self._deleteSelectedEntries)
        btnlo.addWidget(self.wdelbtn)
        # enable status line
        self.statusBar().show()
        Purr.progressMessage = self.message
        self._prev_msg = None
        # editor dialog for new entry
        self.new_entry_dialog = Purr.Editors.NewLogEntryDialog(self)
        self.connect(self.new_entry_dialog, SIGNAL("newLogEntry"),
                     self._newLogEntry)
        self.connect(self.new_entry_dialog, SIGNAL("filesSelected"),
                     self._addDPFiles)
        self.connect(self.wnewbtn, SIGNAL("clicked()"),
                     self.new_entry_dialog.show)
        self.connect(self.new_entry_dialog, SIGNAL("shown"),
                     self._checkPounceStatus)
        # entry viewer dialog
        self.view_entry_dialog = Purr.Editors.ExistingLogEntryDialog(self)
        self.connect(self.view_entry_dialog, SIGNAL("previous()"),
                     self._viewPrevEntry)
        self.connect(self.view_entry_dialog, SIGNAL("next()"),
                     self._viewNextEntry)
        self.connect(self.view_entry_dialog, SIGNAL("viewPath"),
                     self._viewPath)
        self.connect(self.view_entry_dialog, SIGNAL("filesSelected"),
                     self._addDPFilesToOldEntry)
        self.connect(self.view_entry_dialog, SIGNAL("entryChanged"),
                     self._entryChanged)
        # saving a data product to an older entry will automatically drop it from the
        # new entry dialog
        self.connect(self.view_entry_dialog, SIGNAL("creatingDataProduct"),
                     self.new_entry_dialog.dropDataProducts)
        # resize selves
        width = Config.getint('main-window-width', 512)
        height = Config.getint('main-window-height', 512)
        self.resize(QSize(width, height))
        # create timer for pouncing
        self._timer = QTimer(self)
        self.connect(self._timer, SIGNAL("timeout()"), self._rescan)
        # create dict mapping index.html paths to entry numbers
        self._index_paths = {}